diff options
Diffstat (limited to 'roms/ipxe/src/drivers')
129 files changed, 868 insertions, 23921 deletions
diff --git a/roms/ipxe/src/drivers/block/ibft.c b/roms/ipxe/src/drivers/block/ibft.c index 91a808d85..6aabd766a 100644 --- a/roms/ipxe/src/drivers/block/ibft.c +++ b/roms/ipxe/src/drivers/block/ibft.c @@ -260,7 +260,6 @@ static int ibft_fill_nic ( struct ibft_nic *nic, ibft_set_ipaddr_setting ( NULL, &nic->dns[0], &dns_setting, ( sizeof ( nic->dns ) / sizeof ( nic->dns[0] ) ) ); - ibft_set_ipaddr_setting ( parent, &nic->dhcp, &dhcp_server_setting, 1 ); DBG ( "iBFT NIC DNS = %s", ibft_ipaddr ( &nic->dns[0] ) ); DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) ); if ( ( rc = ibft_set_string_setting ( NULL, strings, &nic->hostname, diff --git a/roms/ipxe/src/drivers/bus/pci.c b/roms/ipxe/src/drivers/bus/pci.c index 06b36a770..6fbedd940 100644 --- a/roms/ipxe/src/drivers/bus/pci.c +++ b/roms/ipxe/src/drivers/bus/pci.c @@ -175,7 +175,7 @@ void adjust_pci_device ( struct pci_device *pci ) { * @ret rc Return status code */ int pci_read_config ( struct pci_device *pci ) { - uint32_t busdevfn; + uint16_t busdevfn; uint8_t hdrtype; uint32_t tmp; @@ -203,8 +203,8 @@ int pci_read_config ( struct pci_device *pci ) { pci_read_bases ( pci ); /* Initialise generic device component */ - snprintf ( pci->dev.name, sizeof ( pci->dev.name ), "%04x:%02x:%02x.%x", - PCI_SEG ( pci->busdevfn ), PCI_BUS ( pci->busdevfn ), + snprintf ( pci->dev.name, sizeof ( pci->dev.name ), + "PCI%02x:%02x.%x", PCI_BUS ( pci->busdevfn ), PCI_SLOT ( pci->busdevfn ), PCI_FUNC ( pci->busdevfn ) ); pci->dev.desc.bus_type = BUS_TYPE_PCI; pci->dev.desc.location = pci->busdevfn; @@ -232,7 +232,7 @@ int pci_find_next ( struct pci_device *pci, unsigned int busdevfn ) { /* Determine number of PCI buses */ if ( ! end ) - end = PCI_BUSDEVFN ( 0, pci_num_bus(), 0, 0 ); + end = PCI_BUSDEVFN ( pci_num_bus(), 0, 0 ); /* Find next PCI device, if any */ for ( ; busdevfn < end ; busdevfn++ ) { diff --git a/roms/ipxe/src/drivers/bus/pci_settings.c b/roms/ipxe/src/drivers/bus/pci_settings.c index 98005559d..1cb9fa5a3 100644 --- a/roms/ipxe/src/drivers/bus/pci_settings.c +++ b/roms/ipxe/src/drivers/bus/pci_settings.c @@ -70,7 +70,7 @@ static int pci_settings_fetch ( struct settings *settings __unused, unsigned int i; /* Extract busdevfn, offset, and length from tag */ - tag_busdevfn = ( setting->tag >> 16 ); + tag_busdevfn = ( ( setting->tag >> 16 ) & 0xffff ); tag_offset = ( ( setting->tag >> 8 ) & 0xff ); tag_len = ( ( setting->tag >> 0 ) & 0xff ); diff --git a/roms/ipxe/src/drivers/bus/pciea.c b/roms/ipxe/src/drivers/bus/pciea.c deleted file mode 100644 index aaa69cf4c..000000000 --- a/roms/ipxe/src/drivers/bus/pciea.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <errno.h> -#include <ipxe/pci.h> -#include <ipxe/pciea.h> - -/** @file - * - * PCI Enhanced Allocation - * - */ - -/** - * Locate PCI Enhanced Allocation BAR equivalent entry - * - * @v pci PCI device - * @v bei BAR equivalent indicator - * @ret offset PCI Enhanced Allocation entry offset, or negative error - */ -static int pciea_offset ( struct pci_device *pci, unsigned int bei ) { - uint8_t entries; - uint32_t desc; - unsigned int i; - int offset; - - /* Locate Enhanced Allocation capability */ - offset = pci_find_capability ( pci, PCI_CAP_ID_EA ); - if ( offset < 0 ) - return offset; - - /* Get number of entries */ - pci_read_config_byte ( pci, ( offset + PCIEA_ENTRIES ), &entries ); - entries &= PCIEA_ENTRIES_MASK; - - /* Locate first entry */ - offset += PCIEA_FIRST; - - /* Search for a matching entry */ - for ( i = 0 ; i < entries ; i++ ) { - - /* Read entry descriptor */ - pci_read_config_dword ( pci, offset, &desc ); - - /* Check for a matching entry */ - if ( ( desc & PCIEA_DESC_ENABLED ) && - ( bei == PCIEA_DESC_BEI ( desc ) ) ) - return offset; - - /* Move to next entry */ - offset += ( ( PCIEA_DESC_SIZE ( desc ) + 1 ) << 2 ); - } - - return -ENOENT; -} - -/** - * Read PCI Enhanced Allocation BAR equivalent value - * - * @v pci PCI device - * @v bei BAR equivalent indicator - * @v low_offset Offset to low dword of value - * @ret value BAR equivalent value - */ -static unsigned long pciea_bar_value ( struct pci_device *pci, unsigned int bei, - unsigned int low_offset ) { - uint32_t low; - uint32_t high; - int offset; - - /* Locate Enhanced Allocation offset for this BEI */ - offset = pciea_offset ( pci, bei ); - if ( offset < 0 ) - return 0; - - /* Read BAR equivalent */ - offset += low_offset; - pci_read_config_dword ( pci, offset, &low ); - if ( low & PCIEA_LOW_ATTR_64BIT ) { - offset += PCIEA_LOW_HIGH; - pci_read_config_dword ( pci, offset, &high ); - if ( high ) { - if ( sizeof ( unsigned long ) > sizeof ( uint32_t ) ) { - return ( ( ( uint64_t ) high << 32 ) | low ); - } else { - DBGC ( pci, PCI_FMT " unhandled 64-bit EA BAR " - "%08x%08x\n", - PCI_ARGS ( pci ), high, low ); - return 0; - } - } - } - return low; -} - -/** - * Find the start of a PCI Enhanced Allocation BAR equivalent - * - * @v pci PCI device - * @v bei BAR equivalent indicator - * @ret start BAR start address - * - * If the address exceeds the size of an unsigned long (i.e. if a - * 64-bit BAR has a non-zero high dword on a 32-bit machine), the - * return value will be zero. - */ -unsigned long pciea_bar_start ( struct pci_device *pci, unsigned int bei ) { - unsigned long base; - - base = pciea_bar_value ( pci, bei, PCIEA_LOW_BASE ); - return ( base & ~PCIEA_LOW_ATTR_MASK ); -} - -/** - * Find the size of a PCI Enhanced Allocation BAR equivalent - * - * @v pci PCI device - * @v bei BAR equivalent indicator - * @ret size BAR size - */ -unsigned long pciea_bar_size ( struct pci_device *pci, unsigned int bei ) { - unsigned long limit; - - limit = pciea_bar_value ( pci, bei, PCIEA_LOW_LIMIT ); - return ( limit ? ( ( limit | PCIEA_LOW_ATTR_MASK ) + 1 ) : 0 ); -} diff --git a/roms/ipxe/src/drivers/bus/pciextra.c b/roms/ipxe/src/drivers/bus/pciextra.c index 3082d8a3d..82287fb86 100644 --- a/roms/ipxe/src/drivers/bus/pciextra.c +++ b/roms/ipxe/src/drivers/bus/pciextra.c @@ -3,24 +3,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <stdint.h> #include <ipxe/pci.h> -static int pci_find_capability_common ( struct pci_device *pci, - uint8_t pos, int cap ) { - uint8_t id; - int ttl = 48; - - while ( ttl-- && pos >= 0x40 ) { - pos &= ~3; - pci_read_config_byte ( pci, pos + PCI_CAP_ID, &id ); - DBG ( "PCI Capability: %d\n", id ); - if ( id == 0xff ) - break; - if ( id == cap ) - return pos; - pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &pos ); - } - return 0; -} - /** * Look for a PCI capability * @@ -35,8 +17,9 @@ static int pci_find_capability_common ( struct pci_device *pci, */ int pci_find_capability ( struct pci_device *pci, int cap ) { uint16_t status; - uint8_t pos; + uint8_t pos, id; uint8_t hdr_type; + int ttl = 48; pci_read_config_word ( pci, PCI_STATUS, &status ); if ( ! ( status & PCI_STATUS_CAP_LIST ) ) @@ -53,28 +36,17 @@ int pci_find_capability ( struct pci_device *pci, int cap ) { pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos ); break; } - return pci_find_capability_common ( pci, pos, cap ); -} - -/** - * Look for another PCI capability - * - * @v pci PCI device to query - * @v pos Address of the current capability - * @v cap Capability code - * @ret address Address of capability, or 0 if not found - * - * Determine whether or not a device supports a given PCI capability - * starting the search at a given address within the device's PCI - * configuration space. Returns the address of the next capability - * structure within the device's PCI configuration space, or 0 if the - * device does not support another such capability. - */ -int pci_find_next_capability ( struct pci_device *pci, int pos, int cap ) { - uint8_t new_pos; - - pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &new_pos ); - return pci_find_capability_common ( pci, new_pos, cap ); + while ( ttl-- && pos >= 0x40 ) { + pos &= ~3; + pci_read_config_byte ( pci, pos + PCI_CAP_ID, &id ); + DBG ( "PCI Capability: %d\n", id ); + if ( id == 0xff ) + break; + if ( id == cap ) + return pos; + pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &pos ); + } + return 0; } /** diff --git a/roms/ipxe/src/drivers/bus/usb.c b/roms/ipxe/src/drivers/bus/usb.c index 880e3f08c..2019e3341 100644 --- a/roms/ipxe/src/drivers/bus/usb.c +++ b/roms/ipxe/src/drivers/bus/usb.c @@ -243,6 +243,7 @@ int usb_endpoint_described ( struct usb_endpoint *ep, struct usb_interface_descriptor *interface, unsigned int type, unsigned int index ) { struct usb_device *usb = ep->usb; + struct usb_port *port = usb->port; struct usb_endpoint_descriptor *desc; struct usb_endpoint_companion_descriptor *descx; unsigned int sizes; @@ -266,7 +267,7 @@ int usb_endpoint_described ( struct usb_endpoint *ep, /* Calculate interval */ if ( ( type & USB_ENDPOINT_ATTR_TYPE_MASK ) == USB_ENDPOINT_ATTR_INTERRUPT ) { - if ( usb->speed >= USB_SPEED_HIGH ) { + if ( port->speed >= USB_SPEED_HIGH ) { /* 2^(desc->interval-1) is a microframe count */ interval = ( 1 << ( desc->interval - 1 ) ); } else { @@ -484,7 +485,7 @@ int usb_message ( struct usb_endpoint *ep, unsigned int request, assert ( iob_headroom ( iobuf ) >= sizeof ( *packet ) ); /* Fail immediately if device has been unplugged */ - if ( port->disconnected ) + if ( port->speed == USB_SPEED_NONE ) return -ENODEV; /* Reset endpoint if required */ @@ -529,11 +530,10 @@ int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf, int terminate ) { struct usb_device *usb = ep->usb; struct usb_port *port = usb->port; - int zlp; int rc; /* Fail immediately if device has been unplugged */ - if ( port->disconnected ) + if ( port->speed == USB_SPEED_NONE ) return -ENODEV; /* Reset endpoint if required */ @@ -541,13 +541,8 @@ int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf, ( ( rc = usb_endpoint_reset ( ep ) ) != 0 ) ) return rc; - /* Append a zero-length packet if necessary */ - zlp = terminate; - if ( iob_len ( iobuf ) & ( ep->mtu - 1 ) ) - zlp = 0; - /* Enqueue stream transfer */ - if ( ( rc = ep->host->stream ( ep, iobuf, zlp ) ) != 0 ) { + if ( ( rc = ep->host->stream ( ep, iobuf, terminate ) ) != 0 ) { DBGC ( usb, "USB %s %s could not enqueue stream transfer: %s\n", usb->name, usb_endpoint_name ( ep ), strerror ( rc ) ); return rc; @@ -601,7 +596,6 @@ void usb_complete_err ( struct usb_endpoint *ep, struct io_buffer *iobuf, */ int usb_prefill ( struct usb_endpoint *ep ) { struct io_buffer *iobuf; - size_t reserve = ep->reserve; size_t len = ( ep->len ? ep->len : ep->mtu ); unsigned int fill; int rc; @@ -615,12 +609,11 @@ int usb_prefill ( struct usb_endpoint *ep ) { for ( fill = 0 ; fill < ep->max ; fill++ ) { /* Allocate I/O buffer */ - iobuf = alloc_iob ( reserve + len ); + iobuf = alloc_iob ( len ); if ( ! iobuf ) { rc = -ENOMEM; goto err_alloc; } - iob_reserve ( iobuf, reserve ); /* Add to recycled buffer list */ list_add_tail ( &iobuf->list, &ep->recycled ); @@ -641,7 +634,6 @@ int usb_prefill ( struct usb_endpoint *ep ) { */ int usb_refill ( struct usb_endpoint *ep ) { struct io_buffer *iobuf; - size_t reserve = ep->reserve; size_t len = ( ep->len ? ep->len : ep->mtu ); int rc; @@ -655,10 +647,9 @@ int usb_refill ( struct usb_endpoint *ep ) { /* Get or allocate buffer */ if ( list_empty ( &ep->recycled ) ) { /* Recycled buffer list is empty; allocate new buffer */ - iobuf = alloc_iob ( reserve + len ); + iobuf = alloc_iob ( len ); if ( ! iobuf ) return -ENOMEM; - iob_reserve ( iobuf, reserve ); } else { /* Get buffer from recycled buffer list */ iobuf = list_first_entry ( &ep->recycled, @@ -904,155 +895,75 @@ int usb_get_string_descriptor ( struct usb_device *usb, unsigned int index, */ /** - * Get USB configuration descriptor - * - * @v usb USB device - * @v index Configuration index - * @ret config Configuration descriptor - * @ret rc Return status code - * - * The configuration descriptor is dynamically allocated and must - * eventually be freed by the caller. - */ -static int -usb_config_descriptor ( struct usb_device *usb, unsigned int index, - struct usb_configuration_descriptor **config ) { - struct usb_configuration_descriptor partial; - size_t len; - int rc; - - /* Read first part of configuration descriptor to get size */ - if ( ( rc = usb_get_config_descriptor ( usb, index, &partial, - sizeof ( partial ) ) ) != 0 ) { - DBGC ( usb, "USB %s could not get configuration descriptor %d: " - "%s\n", usb->name, index, strerror ( rc ) ); - goto err_get_partial; - } - len = le16_to_cpu ( partial.len ); - if ( len < sizeof ( partial ) ) { - DBGC ( usb, "USB %s underlength configuraton descriptor %d\n", - usb->name, index ); - rc = -EINVAL; - goto err_partial_len; - } - - /* Allocate buffer for whole configuration descriptor */ - *config = malloc ( len ); - if ( ! *config ) { - rc = -ENOMEM; - goto err_alloc_config; - } - - /* Read whole configuration descriptor */ - if ( ( rc = usb_get_config_descriptor ( usb, index, *config, - len ) ) != 0 ) { - DBGC ( usb, "USB %s could not get configuration descriptor %d: " - "%s\n", usb->name, index, strerror ( rc ) ); - goto err_get_config_descriptor; - } - if ( (*config)->len != partial.len ) { - DBGC ( usb, "USB %s bad configuration descriptor %d length\n", - usb->name, index ); - rc = -EINVAL; - goto err_config_len; - } - - return 0; - - err_config_len: - err_get_config_descriptor: - free ( *config ); - err_alloc_config: - err_partial_len: - err_get_partial: - return rc; -} - -/** * Describe USB function * - * @v usb USB device + * @v func USB function * @v config Configuration descriptor * @v first First interface number - * @v interfaces Interface list to fill in - * @v desc Function descriptor to fill in * @ret rc Return status code */ -static int usb_describe ( struct usb_device *usb, +static int usb_function ( struct usb_function *func, struct usb_configuration_descriptor *config, - unsigned int first, uint8_t *interfaces, - struct usb_function_descriptor *desc ) { + unsigned int first ) { + struct usb_device *usb = func->usb; struct usb_interface_association_descriptor *association; struct usb_interface_descriptor *interface; struct cdc_union_descriptor *cdc_union; unsigned int i; - /* Fill in vendor and product ID */ - memset ( desc, 0, sizeof ( *desc ) ); - desc->vendor = le16_to_cpu ( usb->device.vendor ); - desc->product = le16_to_cpu ( usb->device.product ); - /* First, look for an interface association descriptor */ association = usb_interface_association_descriptor ( config, first ); if ( association ) { /* Sanity check */ - assert ( association->first == first ); - if ( ( first + association->count ) > config->interfaces ) { + if ( association->count > config->interfaces ) { DBGC ( usb, "USB %s has invalid association [%d-%d)\n", - usb->name, first, ( first + association->count)); + func->name, association->first, + ( association->first + association->count ) ); return -ERANGE; } /* Describe function */ - memcpy ( &desc->class, &association->class, - sizeof ( desc->class ) ); - desc->count = association->count; + memcpy ( &func->class, &association->class, + sizeof ( func->class ) ); + func->count = association->count; for ( i = 0 ; i < association->count ; i++ ) - interfaces[i] = ( first + i ); + func->interface[i] = ( association->first + i ); return 0; } /* Next, look for an interface descriptor */ interface = usb_interface_descriptor ( config, first, 0 ); if ( ! interface ) { - DBGC ( usb, "USB %s has no descriptor for interface %d\n", - usb->name, first ); + DBGC ( usb, "USB %s has no interface descriptor\n", + func->name ); return -ENOENT; } /* Describe function */ - memcpy ( &desc->class, &interface->class, sizeof ( desc->class ) ); - desc->count = 1; - interfaces[0] = first; + memcpy ( &func->class, &interface->class, sizeof ( func->class ) ); + func->count = 1; + func->interface[0] = first; /* Look for a CDC union descriptor, if applicable */ - if ( ( desc->class.class.class == USB_CLASS_CDC ) && + if ( ( func->class.class == USB_CLASS_CDC ) && ( cdc_union = cdc_union_descriptor ( config, interface ) ) ) { /* Determine interface count */ - desc->count = ( ( cdc_union->header.len - + func->count = ( ( cdc_union->header.len - offsetof ( typeof ( *cdc_union ), interface[0] ) ) / sizeof ( cdc_union->interface[0] ) ); - if ( desc->count > config->interfaces ) { + if ( func->count > config->interfaces ) { DBGC ( usb, "USB %s has invalid union functional " "descriptor with %d interfaces\n", - usb->name, desc->count ); + func->name, func->count ); return -ERANGE; } /* Describe function */ - for ( i = 0 ; i < desc->count ; i++ ) { - if ( cdc_union->interface[i] >= config->interfaces ) { - DBGC ( usb, "USB %s has invalid union " - "functional descriptor covering " - "interface %d\n", usb->name, - cdc_union->interface[i] ); - return -ERANGE; - } - interfaces[i] = cdc_union->interface[i]; - } + for ( i = 0 ; i < func->count ; i++ ) + func->interface[i] = cdc_union->interface[i]; return 0; } @@ -1061,108 +972,22 @@ static int usb_describe ( struct usb_device *usb, } /** - * Update list of used interface + * Check for a USB device ID match * - * @v usb USB device - * @v count Number of interfaces - * @v interface List of interfaces - * @v used List of already-used interfaces - * @ret rc Return status code - */ -static int usb_used ( struct usb_device *usb, unsigned int count, - uint8_t *interface, uint8_t *used ) { - unsigned int i; - - for ( i = 0 ; i < count ; i++ ) { - if ( used[interface[i]] ) { - DBGC ( usb, "USB %s interface %d already in use\n", - usb->name, interface[i] ); - return -EINVAL; - } - used[interface[i]] = 1; - } - return 0; -} - -/** - * Find USB device driver - * - * @v desc Function descriptor - * @ret id USB device ID, or NULL - * @ret driver USB device driver, or NULL - */ -struct usb_driver * usb_find_driver ( struct usb_function_descriptor *desc, - struct usb_device_id **id ) { - struct usb_driver *driver; - unsigned int i; - - /* Look for a matching driver */ - for_each_table_entry ( driver, USB_DRIVERS ) { - for ( i = 0 ; i < driver->id_count ; i++ ) { - - /* Ignore non-matching driver class */ - if ( ( driver->class.class.scalar ^ desc->class.scalar ) - & driver->class.mask.scalar ) - continue; - - /* Look for a matching ID */ - *id = &driver->ids[i]; - if ( ( ( (*id)->vendor == desc->vendor ) || - ( (*id)->vendor == USB_ANY_ID ) ) && - ( ( (*id)->product == desc->product ) || - ( (*id)->product == USB_ANY_ID ) ) ) - return driver; - } - } - - /* Not found */ - *id = NULL; - return NULL; -} - -/** - * Get USB device configuration score - * - * @v usb USB device - * @v config Configuration descriptor - * @ret score Device configuration score, or negative error + * @v func USB function + * @v id Device ID + * @ret matches Device ID matches */ -static int usb_score ( struct usb_device *usb, - struct usb_configuration_descriptor *config ) { - uint8_t used[config->interfaces]; - uint8_t interface[config->interfaces]; - struct usb_function_descriptor desc; - struct usb_driver *driver; - struct usb_device_id *id; - unsigned int first; - unsigned int score = 0; - int rc; - - /* Identify each function in turn */ - memset ( used, 0, sizeof ( used ) ); - for ( first = 0 ; first < config->interfaces ; first++ ) { - - /* Skip interfaces already used */ - if ( used[first] ) - continue; - - /* Describe function */ - if ( ( rc = usb_describe ( usb, config, first, interface, - &desc ) ) != 0 ) - return rc; - - /* Update used interfaces */ - if ( ( rc = usb_used ( usb, desc.count, interface, - used ) ) != 0 ) - return rc; - - /* Look for a driver for this function */ - driver = usb_find_driver ( &desc, &id ); - if ( driver ) - score += driver->score; - } - - return score; +static int +usb_device_id_matches ( struct usb_function *func, struct usb_device_id *id ) { + + return ( ( ( id->vendor == func->dev.desc.vendor ) || + ( id->vendor == USB_ANY_ID ) ) && + ( ( id->product == func->dev.desc.device ) || + ( id->product == USB_ANY_ID ) ) && + ( id->class.class == func->class.class ) && + ( id->class.subclass == func->class.subclass ) && + ( id->class.protocol == func->class.protocol ) ); } /** @@ -1177,32 +1002,39 @@ static int usb_probe ( struct usb_function *func, struct usb_device *usb = func->usb; struct usb_driver *driver; struct usb_device_id *id; + unsigned int i; int rc; - /* Identify driver */ - driver = usb_find_driver ( &func->desc, &id ); - if ( ! driver ) { - DBGC ( usb, "USB %s %04x:%04x class %d:%d:%d has no driver\n", - func->name, func->desc.vendor, func->desc.product, - func->desc.class.class.class, - func->desc.class.class.subclass, - func->desc.class.class.protocol ); - return -ENOENT; - } + /* Look for a matching driver */ + for_each_table_entry ( driver, USB_DRIVERS ) { + for ( i = 0 ; i < driver->id_count ; i++ ) { - /* Record driver */ - func->driver = driver; - func->id = id; - func->dev.driver_name = id->name; + /* Check for a matching ID */ + id = &driver->ids[i]; + if ( ! usb_device_id_matches ( func, id ) ) + continue; - /* Probe driver */ - if ( ( rc = driver->probe ( func, config ) ) != 0 ) { - DBGC ( usb, "USB %s failed to probe driver %s: %s\n", - func->name, id->name, strerror ( rc ) ); - return rc; + /* Probe driver */ + if ( ( rc = driver->probe ( func, config ) ) != 0 ) { + DBGC ( usb, "USB %s failed to probe driver %s: " + "%s\n", func->name, id->name, + strerror ( rc ) ); + /* Continue trying other drivers */ + continue; + } + + /* Record driver */ + func->driver = driver; + func->dev.driver_name = id->name; + return 0; + } } - return 0; + /* No driver found */ + DBGC ( usb, "USB %s %04x:%04x class %d:%d:%d has no driver\n", + func->name, func->dev.desc.vendor, func->dev.desc.device, + func->class.class, func->class.subclass, func->class.protocol ); + return -ENOENT; } /** @@ -1256,45 +1088,50 @@ usb_probe_all ( struct usb_device *usb, "%s-%d.%d", usb->name, config->config, first ); INIT_LIST_HEAD ( &func->dev.children ); func->dev.parent = bus->dev; - list_add_tail ( &func->list, &usb->functions ); /* Identify function */ - if ( ( rc = usb_describe ( usb, config, first, func->interface, - &func->desc ) ) != 0 ) - goto err_describe; - assert ( func->desc.count <= config->interfaces ); + if ( ( rc = usb_function ( func, config, first ) ) != 0 ) + goto err_function; + assert ( func->count <= config->interfaces ); /* Mark interfaces as used */ - if ( ( rc = usb_used ( usb, func->desc.count, func->interface, - used ) ) != 0 ) - goto err_used; + for ( i = 0 ; i < func->count ; i++ ) { + if ( func->interface[i] >= config->interfaces ) { + DBGC ( usb, "USB %s has invalid interface %d\n", + func->name, func->interface[i] ); + goto err_interface; + } + used[ func->interface[i] ] = 1; + } /* Probe device driver */ if ( ( rc = usb_probe ( func, config ) ) != 0 ) goto err_probe; DBGC ( usb, "USB %s %04x:%04x class %d:%d:%d interfaces ", - func->name, func->desc.vendor, func->desc.product, - func->desc.class.class.class, - func->desc.class.class.subclass, - func->desc.class.class.protocol ); - for ( i = 0 ; i < func->desc.count ; i++ ) + func->name, func->dev.desc.vendor, func->dev.desc.device, + func->class.class, func->class.subclass, + func->class.protocol ); + for ( i = 0 ; i < func->count ; i++ ) DBGC ( usb, "%s%d", ( i ? "," : "" ), func->interface[i] ); DBGC ( usb, " using driver %s\n", func->dev.driver_name ); + /* Add to list of functions */ + list_add ( &func->list, &usb->functions ); + /* Add to device hierarchy */ list_add_tail ( &func->dev.siblings, &bus->dev->children ); continue; list_del ( &func->dev.siblings ); + list_del ( &func->list ); usb_remove ( func ); err_probe: - err_used: - err_describe: - list_del ( &func->list ); free ( func ); err_alloc: + err_interface: + err_function: /* Continue registering other functions */ continue; } @@ -1328,6 +1165,82 @@ static void usb_remove_all ( struct usb_device *usb ) { } /** + * Select USB device configuration + * + * @v usb USB device + * @v index Configuration index + * @ret rc Return status code + */ +static int usb_configure ( struct usb_device *usb, unsigned int index ) { + struct usb_configuration_descriptor partial; + struct usb_configuration_descriptor *config; + size_t len; + int rc; + + /* Read first part of configuration descriptor to get size */ + if ( ( rc = usb_get_config_descriptor ( usb, index, &partial, + sizeof ( partial ) ) ) != 0 ) { + DBGC ( usb, "USB %s could not get configuration descriptor %d: " + "%s\n", usb->name, index, strerror ( rc ) ); + goto err_get_partial; + } + len = le16_to_cpu ( partial.len ); + if ( len < sizeof ( partial ) ) { + DBGC ( usb, "USB %s underlength configuraton descriptor %d\n", + usb->name, index ); + rc = -EINVAL; + goto err_partial_len; + } + + /* Allocate buffer for whole configuration descriptor */ + config = malloc ( len ); + if ( ! config ) { + rc = -ENOMEM; + goto err_alloc_config; + } + + /* Read whole configuration descriptor */ + if ( ( rc = usb_get_config_descriptor ( usb, index, config, + len ) ) != 0 ) { + DBGC ( usb, "USB %s could not get configuration descriptor %d: " + "%s\n", usb->name, index, strerror ( rc ) ); + goto err_get_config_descriptor; + } + if ( config->len != partial.len ) { + DBGC ( usb, "USB %s bad configuration descriptor %d length\n", + usb->name, index ); + rc = -EINVAL; + goto err_config_len; + } + + /* Set configuration */ + if ( ( rc = usb_set_configuration ( usb, config->config ) ) != 0){ + DBGC ( usb, "USB %s could not set configuration %d: %s\n", + usb->name, config->config, strerror ( rc ) ); + goto err_set_configuration; + } + + /* Probe USB device drivers */ + usb_probe_all ( usb, config ); + + /* Free configuration descriptor */ + free ( config ); + + return 0; + + usb_remove_all ( usb ); + usb_set_configuration ( usb, 0 ); + err_set_configuration: + err_config_len: + err_get_config_descriptor: + free ( config ); + err_alloc_config: + err_partial_len: + err_get_partial: + return rc; +} + +/** * Clear USB device configuration * * @v usb USB device @@ -1349,76 +1262,32 @@ static void usb_deconfigure ( struct usb_device *usb ) { } /** - * Choose our preferred USB device configuration + * Find and select a supported USB device configuration * * @v usb USB device * @ret rc Return status code */ -static int usb_autoconfigure ( struct usb_device *usb ) { - struct usb_configuration_descriptor *config; - unsigned int preferred = 0; +static int usb_configure_any ( struct usb_device *usb ) { unsigned int index; - int score; - int best = 0; - int rc; + int rc = -ENOENT; - /* Calculate driver score for each configuration index */ + /* Attempt all configuration indexes */ for ( index = 0 ; index < usb->device.configurations ; index++ ) { - /* Read configuration descriptor */ - if ( ( rc = usb_config_descriptor ( usb, index, - &config ) ) != 0 ) - goto err_config; - - /* Get score for this configuration */ - score = usb_score ( usb, config ); - if ( score < 0 ) { - rc = score; - goto err_score; - } - DBGC2 ( usb, "USB %s configuration %d score %d\n", - usb->name, config->config, score ); + /* Attempt this configuration index */ + if ( ( rc = usb_configure ( usb, index ) ) != 0 ) + continue; - /* Record as preferred configuration, if applicable */ - if ( score > best ) { - best = score; - preferred = index; + /* If we have no drivers, then try the next configuration */ + if ( list_empty ( &usb->functions ) ) { + rc = -ENOTSUP; + usb_deconfigure ( usb ); + continue; } - /* Free configuration descriptor */ - free ( config ); - config = NULL; - } - - /* Read preferred configuration descriptor */ - if ( ( rc = usb_config_descriptor ( usb, preferred, &config ) ) != 0 ) - goto err_preferred; - - /* Set configuration */ - if ( ( rc = usb_set_configuration ( usb, config->config ) ) != 0){ - DBGC ( usb, "USB %s could not set configuration %d: %s\n", - usb->name, config->config, strerror ( rc ) ); - goto err_set_configuration; + return 0; } - /* Probe USB device drivers */ - usb_probe_all ( usb, config ); - - /* Free configuration descriptor */ - free ( config ); - - return 0; - - usb_remove_all ( usb ); - usb_set_configuration ( usb, 0 ); - err_set_configuration: - free ( config ); - err_preferred: - return rc; - - err_score: - free ( config ); - err_config: return rc; } @@ -1497,9 +1366,8 @@ static int register_usb ( struct usb_device *usb ) { hub->name, port->address, strerror ( rc ) ); goto err_speed; } - usb->speed = port->speed; DBGC2 ( usb, "USB %s attached as %s-speed device\n", - usb->name, usb_speed_name ( usb->speed ) ); + usb->name, usb_speed_name ( port->speed ) ); /* Open device */ if ( ( rc = usb->host->open ( usb ) ) != 0 ) { @@ -1509,7 +1377,7 @@ static int register_usb ( struct usb_device *usb ) { } /* Describe control endpoint */ - mtu = USB_EP0_DEFAULT_MTU ( usb->speed ); + mtu = USB_EP0_DEFAULT_MTU ( port->speed ); usb_endpoint_describe ( &usb->control, USB_EP0_ADDRESS, USB_EP0_ATTRIBUTES, mtu, USB_EP0_BURST, USB_EP0_INTERVAL ); @@ -1560,16 +1428,16 @@ static int register_usb ( struct usb_device *usb ) { le16_to_cpu ( usb->device.product ), usb->device.class.class, usb->device.class.subclass, usb->device.class.protocol, usb_bcd ( le16_to_cpu ( usb->device.protocol ) ), - usb_speed_name ( usb->speed ), usb->control.mtu ); + usb_speed_name ( port->speed ), usb->control.mtu ); /* Configure device */ - if ( ( rc = usb_autoconfigure ( usb ) ) != 0 ) - goto err_autoconfigure; + if ( ( rc = usb_configure_any ( usb ) ) != 0 ) + goto err_configure_any; return 0; usb_deconfigure ( usb ); - err_autoconfigure: + err_configure_any: err_get_device_descriptor: err_mtu: err_get_mtu: @@ -1723,24 +1591,23 @@ static int usb_hotplugged ( struct usb_port *port ) { if ( ( rc = hub->driver->speed ( hub, port ) ) != 0 ) { DBGC ( hub, "USB hub %s port %d could not get speed: %s\n", hub->name, port->address, strerror ( rc ) ); - /* Treat as a disconnection */ - port->disconnected = 1; - port->speed = USB_SPEED_NONE; + goto err_speed; } /* Detach device, if applicable */ if ( port->attached && ( port->disconnected || ! port->speed ) ) usb_detached ( port ); - /* Clear any recorded disconnections */ - port->disconnected = 0; - /* Attach device, if applicable */ if ( port->speed && ( ! port->attached ) && ( ( rc = usb_attached ( port ) ) != 0 ) ) - return rc; + goto err_attached; - return 0; + err_attached: + err_speed: + /* Clear any recorded disconnections */ + port->disconnected = 0; + return rc; } /****************************************************************************** @@ -2239,12 +2106,12 @@ struct usb_port * usb_transaction_translator ( struct usb_device *usb ) { struct usb_device *parent; /* Navigate up to root hub. If we find a low-speed or - * full-speed device with a higher-speed parent hub, then that - * device's port is the transaction translator. + * full-speed port with a higher-speed parent device, then + * that port is the transaction translator. */ for ( ; ( parent = usb->port->hub->usb ) ; usb = parent ) { - if ( ( usb->speed <= USB_SPEED_FULL ) && - ( parent->speed > USB_SPEED_FULL ) ) + if ( ( usb->port->speed <= USB_SPEED_FULL ) && + ( parent->port->speed > USB_SPEED_FULL ) ) return usb->port; } diff --git a/roms/ipxe/src/drivers/bus/virtio-pci.c b/roms/ipxe/src/drivers/bus/virtio-pci.c index 3311595fb..fbef067bc 100644 --- a/roms/ipxe/src/drivers/bus/virtio-pci.c +++ b/roms/ipxe/src/drivers/bus/virtio-pci.c @@ -11,15 +11,10 @@ * */ -#include "errno.h" -#include "byteswap.h" #include "etherboot.h" #include "ipxe/io.h" -#include "ipxe/iomap.h" -#include "ipxe/pci.h" -#include "ipxe/reboot.h" -#include "ipxe/virtio-pci.h" #include "ipxe/virtio-ring.h" +#include "ipxe/virtio-pci.h" int vp_find_vq(unsigned int ioaddr, int queue_index, struct vring_virtqueue *vq) @@ -35,19 +30,19 @@ int vp_find_vq(unsigned int ioaddr, int queue_index, num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM); if (!num) { - DBG("VIRTIO-PCI ERROR: queue size is 0\n"); + printf("ERROR: queue size is 0\n"); return -1; } if (num > MAX_QUEUE_NUM) { - DBG("VIRTIO-PCI ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); + printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); return -1; } /* check if the queue is already active */ if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) { - DBG("VIRTIO-PCI ERROR: queue already active\n"); + printf("ERROR: queue already active\n"); return -1; } @@ -67,343 +62,3 @@ int vp_find_vq(unsigned int ioaddr, int queue_index, return num; } - -#define CFG_POS(vdev, field) \ - (vdev->cfg_cap_pos + offsetof(struct virtio_pci_cfg_cap, field)) - -static void prep_pci_cfg_cap(struct virtio_pci_modern_device *vdev, - struct virtio_pci_region *region, - size_t offset, u32 length) -{ - pci_write_config_byte(vdev->pci, CFG_POS(vdev, cap.bar), region->bar); - pci_write_config_dword(vdev->pci, CFG_POS(vdev, cap.length), length); - pci_write_config_dword(vdev->pci, CFG_POS(vdev, cap.offset), - (intptr_t)(region->base + offset)); -} - -void vpm_iowrite8(struct virtio_pci_modern_device *vdev, - struct virtio_pci_region *region, u8 data, size_t offset) -{ - switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { - case VIRTIO_PCI_REGION_MEMORY: - writeb(data, region->base + offset); - break; - case VIRTIO_PCI_REGION_PORT: - outb(data, region->base + offset); - break; - case VIRTIO_PCI_REGION_PCI_CONFIG: - prep_pci_cfg_cap(vdev, region, offset, 1); - pci_write_config_byte(vdev->pci, CFG_POS(vdev, pci_cfg_data), data); - break; - default: - assert(0); - break; - } -} - -void vpm_iowrite16(struct virtio_pci_modern_device *vdev, - struct virtio_pci_region *region, u16 data, size_t offset) -{ - data = cpu_to_le16(data); - switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { - case VIRTIO_PCI_REGION_MEMORY: - writew(data, region->base + offset); - break; - case VIRTIO_PCI_REGION_PORT: - outw(data, region->base + offset); - break; - case VIRTIO_PCI_REGION_PCI_CONFIG: - prep_pci_cfg_cap(vdev, region, offset, 2); - pci_write_config_word(vdev->pci, CFG_POS(vdev, pci_cfg_data), data); - break; - default: - assert(0); - break; - } -} - -void vpm_iowrite32(struct virtio_pci_modern_device *vdev, - struct virtio_pci_region *region, u32 data, size_t offset) -{ - data = cpu_to_le32(data); - switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { - case VIRTIO_PCI_REGION_MEMORY: - writel(data, region->base + offset); - break; - case VIRTIO_PCI_REGION_PORT: - outl(data, region->base + offset); - break; - case VIRTIO_PCI_REGION_PCI_CONFIG: - prep_pci_cfg_cap(vdev, region, offset, 4); - pci_write_config_dword(vdev->pci, CFG_POS(vdev, pci_cfg_data), data); - break; - default: - assert(0); - break; - } -} - -u8 vpm_ioread8(struct virtio_pci_modern_device *vdev, - struct virtio_pci_region *region, size_t offset) -{ - uint8_t data; - switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { - case VIRTIO_PCI_REGION_MEMORY: - data = readb(region->base + offset); - break; - case VIRTIO_PCI_REGION_PORT: - data = inb(region->base + offset); - break; - case VIRTIO_PCI_REGION_PCI_CONFIG: - prep_pci_cfg_cap(vdev, region, offset, 1); - pci_read_config_byte(vdev->pci, CFG_POS(vdev, pci_cfg_data), &data); - break; - default: - assert(0); - data = 0; - break; - } - return data; -} - -u16 vpm_ioread16(struct virtio_pci_modern_device *vdev, - struct virtio_pci_region *region, size_t offset) -{ - uint16_t data; - switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { - case VIRTIO_PCI_REGION_MEMORY: - data = readw(region->base + offset); - break; - case VIRTIO_PCI_REGION_PORT: - data = inw(region->base + offset); - break; - case VIRTIO_PCI_REGION_PCI_CONFIG: - prep_pci_cfg_cap(vdev, region, offset, 2); - pci_read_config_word(vdev->pci, CFG_POS(vdev, pci_cfg_data), &data); - break; - default: - assert(0); - data = 0; - break; - } - return le16_to_cpu(data); -} - -u32 vpm_ioread32(struct virtio_pci_modern_device *vdev, - struct virtio_pci_region *region, size_t offset) -{ - uint32_t data; - switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { - case VIRTIO_PCI_REGION_MEMORY: - data = readw(region->base + offset); - break; - case VIRTIO_PCI_REGION_PORT: - data = inw(region->base + offset); - break; - case VIRTIO_PCI_REGION_PCI_CONFIG: - prep_pci_cfg_cap(vdev, region, offset, 4); - pci_read_config_dword(vdev->pci, CFG_POS(vdev, pci_cfg_data), &data); - break; - default: - assert(0); - data = 0; - break; - } - return le32_to_cpu(data); -} - -int virtio_pci_find_capability(struct pci_device *pci, uint8_t cfg_type) -{ - int pos; - uint8_t type, bar; - - for (pos = pci_find_capability(pci, PCI_CAP_ID_VNDR); - pos > 0; - pos = pci_find_next_capability(pci, pos, PCI_CAP_ID_VNDR)) { - - pci_read_config_byte(pci, pos + offsetof(struct virtio_pci_cap, - cfg_type), &type); - pci_read_config_byte(pci, pos + offsetof(struct virtio_pci_cap, - bar), &bar); - - /* Ignore structures with reserved BAR values */ - if (bar > 0x5) { - continue; - } - - if (type == cfg_type) { - return pos; - } - } - return 0; -} - -int virtio_pci_map_capability(struct pci_device *pci, int cap, size_t minlen, - u32 align, u32 start, u32 size, - struct virtio_pci_region *region) -{ - u8 bar; - u32 offset, length, base_raw; - unsigned long base; - - pci_read_config_byte(pci, cap + offsetof(struct virtio_pci_cap, bar), &bar); - pci_read_config_dword(pci, cap + offsetof(struct virtio_pci_cap, offset), - &offset); - pci_read_config_dword(pci, cap + offsetof(struct virtio_pci_cap, length), - &length); - - if (length <= start) { - DBG("VIRTIO-PCI bad capability len %d (>%d expected)\n", length, start); - return -EINVAL; - } - if (length - start < minlen) { - DBG("VIRTIO-PCI bad capability len %d (>=%zd expected)\n", length, minlen); - return -EINVAL; - } - length -= start; - if (start + offset < offset) { - DBG("VIRTIO-PCI map wrap-around %d+%d\n", start, offset); - return -EINVAL; - } - offset += start; - if (offset & (align - 1)) { - DBG("VIRTIO-PCI offset %d not aligned to %d\n", offset, align); - return -EINVAL; - } - if (length > size) { - length = size; - } - - if (minlen + offset < minlen || - minlen + offset > pci_bar_size(pci, PCI_BASE_ADDRESS(bar))) { - DBG("VIRTIO-PCI map virtio %zd@%d out of range on bar %i length %ld\n", - minlen, offset, - bar, pci_bar_size(pci, PCI_BASE_ADDRESS(bar))); - return -EINVAL; - } - - region->base = NULL; - region->length = length; - region->bar = bar; - - base = pci_bar_start(pci, PCI_BASE_ADDRESS(bar)); - if (base) { - pci_read_config_dword(pci, PCI_BASE_ADDRESS(bar), &base_raw); - - if (base_raw & PCI_BASE_ADDRESS_SPACE_IO) { - /* Region accessed using port I/O */ - region->base = (void *)(base + offset); - region->flags = VIRTIO_PCI_REGION_PORT; - } else { - /* Region mapped into memory space */ - region->base = ioremap(base + offset, length); - region->flags = VIRTIO_PCI_REGION_MEMORY; - } - } - if (!region->base) { - /* Region accessed via PCI config space window */ - region->base = (void *)(intptr_t)offset; - region->flags = VIRTIO_PCI_REGION_PCI_CONFIG; - } - return 0; -} - -void virtio_pci_unmap_capability(struct virtio_pci_region *region) -{ - unsigned region_type = region->flags & VIRTIO_PCI_REGION_TYPE_MASK; - if (region_type == VIRTIO_PCI_REGION_MEMORY) { - iounmap(region->base); - } -} - -void vpm_notify(struct virtio_pci_modern_device *vdev, - struct vring_virtqueue *vq) -{ - vpm_iowrite16(vdev, &vq->notification, (u16)vq->queue_index, 0); -} - -int vpm_find_vqs(struct virtio_pci_modern_device *vdev, - unsigned nvqs, struct vring_virtqueue *vqs) -{ - unsigned i; - struct vring_virtqueue *vq; - u16 size, off; - u32 notify_offset_multiplier; - int err; - - if (nvqs > vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(num_queues))) { - return -ENOENT; - } - - /* Read notify_off_multiplier from config space. */ - pci_read_config_dword(vdev->pci, - vdev->notify_cap_pos + offsetof(struct virtio_pci_notify_cap, - notify_off_multiplier), - ¬ify_offset_multiplier); - - for (i = 0; i < nvqs; i++) { - /* Select the queue we're interested in */ - vpm_iowrite16(vdev, &vdev->common, (u16)i, COMMON_OFFSET(queue_select)); - - /* Check if queue is either not available or already active. */ - size = vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(queue_size)); - /* QEMU has a bug where queues don't revert to inactive on device - * reset. Skip checking the queue_enable field until it is fixed. - */ - if (!size /*|| vpm_ioread16(vdev, &vdev->common.queue_enable)*/) - return -ENOENT; - - if (size & (size - 1)) { - DBG("VIRTIO-PCI %p: bad queue size %d", vdev, size); - return -EINVAL; - } - - vq = &vqs[i]; - vq->queue_index = i; - - /* get offset of notification word for this vq */ - off = vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(queue_notify_off)); - vq->vring.num = size; - - vring_init(&vq->vring, size, (unsigned char *)vq->queue); - - /* activate the queue */ - vpm_iowrite16(vdev, &vdev->common, size, COMMON_OFFSET(queue_size)); - - vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.desc), - COMMON_OFFSET(queue_desc_lo), - COMMON_OFFSET(queue_desc_hi)); - vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.avail), - COMMON_OFFSET(queue_avail_lo), - COMMON_OFFSET(queue_avail_hi)); - vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.used), - COMMON_OFFSET(queue_used_lo), - COMMON_OFFSET(queue_used_hi)); - - err = virtio_pci_map_capability(vdev->pci, - vdev->notify_cap_pos, 2, 2, - off * notify_offset_multiplier, 2, - &vq->notification); - if (err) { - goto err_map_notify; - } - } - - /* Select and activate all queues. Has to be done last: once we do - * this, there's no way to go back except reset. - */ - for (i = 0; i < nvqs; i++) { - vq = &vqs[i]; - vpm_iowrite16(vdev, &vdev->common, (u16)vq->queue_index, - COMMON_OFFSET(queue_select)); - vpm_iowrite16(vdev, &vdev->common, 1, COMMON_OFFSET(queue_enable)); - } - return 0; - -err_map_notify: - /* Undo the virtio_pci_map_capability calls. */ - while (i-- > 0) { - virtio_pci_unmap_capability(&vqs[i].notification); - } - return err; -} diff --git a/roms/ipxe/src/drivers/bus/virtio-ring.c b/roms/ipxe/src/drivers/bus/virtio-ring.c index 98e787e16..e55b6d0ed 100644 --- a/roms/ipxe/src/drivers/bus/virtio-ring.c +++ b/roms/ipxe/src/drivers/bus/virtio-ring.c @@ -18,8 +18,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include "etherboot.h" #include "ipxe/io.h" -#include "ipxe/virtio-pci.h" #include "ipxe/virtio-ring.h" +#include "ipxe/virtio-pci.h" #define BUG() do { \ printf("BUG: failure at %s:%d/%s()!\n", \ @@ -122,8 +122,7 @@ void vring_add_buf(struct vring_virtqueue *vq, wmb(); } -void vring_kick(struct virtio_pci_modern_device *vdev, unsigned int ioaddr, - struct vring_virtqueue *vq, int num_added) +void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added) { struct vring *vr = &vq->vring; @@ -131,13 +130,7 @@ void vring_kick(struct virtio_pci_modern_device *vdev, unsigned int ioaddr, vr->avail->idx += num_added; mb(); - if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY)) { - if (vdev) { - /* virtio 1.0 */ - vpm_notify(vdev, vq); - } else { - /* legacy virtio */ - vp_notify(ioaddr, vq->queue_index); - } - } + if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY)) + vp_notify(ioaddr, vq->queue_index); } + diff --git a/roms/ipxe/src/drivers/infiniband/CIB_PRM.h b/roms/ipxe/src/drivers/infiniband/CIB_PRM.h deleted file mode 100755 index 6d07c0151..000000000 --- a/roms/ipxe/src/drivers/infiniband/CIB_PRM.h +++ /dev/null @@ -1,1168 +0,0 @@ -/* - * Copyright (C) 2013-2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef __CIB_PRM__ -#define __CIB_PRM__ - -typedef unsigned long long __be64; -typedef uint32_t __be32; -typedef uint16_t __be16; - -#define GOLAN_CMD_DATA_BLOCK_SIZE (1 << 9) -#define GOLAN_CMD_PAS_CNT (GOLAN_CMD_DATA_BLOCK_SIZE / sizeof(__be64)) -#define MAILBOX_STRIDE (1 << 10) -#define MAILBOX_MASK (MAILBOX_STRIDE - 1) - -#define GOLAN_PCI_CMD_XPORT 7 -#define CMD_OWNER_HW 0x1 - -#define IB_NUM_PKEYS 0x20 - -struct health_buffer { - __be32 assert_var[5]; - __be32 rsvd0[3]; - __be32 assert_exit_ptr; - __be32 assert_callra; - __be32 rsvd1[2]; - __be32 fw_ver; - __be32 hw_id; - __be32 rsvd2; - u8 irisc_index; - u8 synd; - __be16 ext_sync; -} __attribute ( ( packed ) ); - -struct golan_hca_init_seg { - __be32 fw_rev; - __be32 cmdif_rev_fw_sub; - __be32 rsvd0[2]; - __be32 cmdq_addr_h; - __be32 cmdq_addr_l_sz; - __be32 cmd_dbell; - __be32 rsvd1[121]; - struct health_buffer health; - __be32 rsvd2[884]; - __be32 health_counter; - __be32 rsvd3[1023]; - __be64 ieee1588_clk; - __be32 ieee1588_clk_type; - __be32 clr_intx; -} __attribute ( ( packed ) ); - -enum golan_manage_pages_mode { - GOLAN_PAGES_CANT_GIVE = 0, - GOLAN_PAGES_GIVE = 1, - GOLAN_PAGES_TAKE = 2 -}; - -enum golan_qry_pages_mode { - GOLAN_BOOT_PAGES = 0x1, - GOLAN_INIT_PAGES = 0x2, - GOLAN_REG_PAGES = 0x3, -}; - -enum { - GOLAN_REG_PCAP = 0x5001, - GOLAN_REG_PMTU = 0x5003, - GOLAN_REG_PTYS = 0x5004, - GOLAN_REG_PAOS = 0x5006, - GOLAN_REG_PMAOS = 0x5012, - GOLAN_REG_PUDE = 0x5009, - GOLAN_REG_PMPE = 0x5010, - GOLAN_REG_PELC = 0x500e, - GOLAN_REG_PMLP = 0, /* TBD */ - GOLAN_REG_NODE_DESC = 0x6001, - GOLAN_REG_HOST_ENDIANESS = 0x7004, -}; - -enum { - GOLAN_CMD_OP_QUERY_HCA_CAP = 0x100, - GOLAN_CMD_OP_QUERY_ADAPTER = 0x101, - GOLAN_CMD_OP_INIT_HCA = 0x102, - GOLAN_CMD_OP_TEARDOWN_HCA = 0x103, - GOLAN_CMD_OP_ENABLE_HCA = 0x104, - GOLAN_CMD_OP_DISABLE_HCA = 0x105, - - GOLAN_CMD_OP_QUERY_PAGES = 0x107, - GOLAN_CMD_OP_MANAGE_PAGES = 0x108, - GOLAN_CMD_OP_SET_HCA_CAP = 0x109, - - GOLAN_CMD_OP_CREATE_MKEY = 0x200, - GOLAN_CMD_OP_QUERY_MKEY = 0x201, - GOLAN_CMD_OP_DESTROY_MKEY = 0x202, - GOLAN_CMD_OP_QUERY_SPECIAL_CONTEXTS = 0x203, - - GOLAN_CMD_OP_CREATE_EQ = 0x301, - GOLAN_CMD_OP_DESTROY_EQ = 0x302, - GOLAN_CMD_OP_QUERY_EQ = 0x303, - - GOLAN_CMD_OP_CREATE_CQ = 0x400, - GOLAN_CMD_OP_DESTROY_CQ = 0x401, - GOLAN_CMD_OP_QUERY_CQ = 0x402, - GOLAN_CMD_OP_MODIFY_CQ = 0x403, - - GOLAN_CMD_OP_CREATE_QP = 0x500, - GOLAN_CMD_OP_DESTROY_QP = 0x501, - GOLAN_CMD_OP_RST2INIT_QP = 0x502, - GOLAN_CMD_OP_INIT2RTR_QP = 0x503, - GOLAN_CMD_OP_RTR2RTS_QP = 0x504, - GOLAN_CMD_OP_RTS2RTS_QP = 0x505, - GOLAN_CMD_OP_SQERR2RTS_QP = 0x506, - GOLAN_CMD_OP_2ERR_QP = 0x507, - GOLAN_CMD_OP_RTS2SQD_QP = 0x508, - GOLAN_CMD_OP_SQD2RTS_QP = 0x509, - GOLAN_CMD_OP_2RST_QP = 0x50a, - GOLAN_CMD_OP_QUERY_QP = 0x50b, - GOLAN_CMD_OP_CONF_SQP = 0x50c, - GOLAN_CMD_OP_MAD_IFC = 0x50d, - GOLAN_CMD_OP_INIT2INIT_QP = 0x50e, - GOLAN_CMD_OP_SUSPEND_QP = 0x50f, - GOLAN_CMD_OP_UNSUSPEND_QP = 0x510, - GOLAN_CMD_OP_SQD2SQD_QP = 0x511, - GOLAN_CMD_OP_ALLOC_QP_COUNTER_SET = 0x512, - GOLAN_CMD_OP_DEALLOC_QP_COUNTER_SET = 0x513, - GOLAN_CMD_OP_QUERY_QP_COUNTER_SET = 0x514, - - GOLAN_CMD_OP_CREATE_PSV = 0x600, - GOLAN_CMD_OP_DESTROY_PSV = 0x601, - GOLAN_CMD_OP_QUERY_PSV = 0x602, - GOLAN_CMD_OP_QUERY_SIG_RULE_TABLE = 0x603, - GOLAN_CMD_OP_QUERY_BLOCK_SIZE_TABLE = 0x604, - - GOLAN_CMD_OP_CREATE_SRQ = 0x700, - GOLAN_CMD_OP_DESTROY_SRQ = 0x701, - GOLAN_CMD_OP_QUERY_SRQ = 0x702, - GOLAN_CMD_OP_ARM_RQ = 0x703, - GOLAN_CMD_OP_RESIZE_SRQ = 0x704, - - GOLAN_CMD_OP_QUERY_HCA_VPORT_CONTEXT = 0x762, - GOLAN_CMD_OP_QUERY_HCA_VPORT_GID = 0x764, - GOLAN_CMD_OP_QUERY_HCA_VPORT_PKEY = 0x765, - - GOLAN_CMD_OP_ALLOC_PD = 0x800, - GOLAN_CMD_OP_DEALLOC_PD = 0x801, - GOLAN_CMD_OP_ALLOC_UAR = 0x802, - GOLAN_CMD_OP_DEALLOC_UAR = 0x803, - - GOLAN_CMD_OP_ATTACH_TO_MCG = 0x806, - GOLAN_CMD_OP_DETACH_FROM_MCG = 0x807, - - - GOLAN_CMD_OP_ALLOC_XRCD = 0x80e, - GOLAN_CMD_OP_DEALLOC_XRCD = 0x80f, - - GOLAN_CMD_OP_ACCESS_REG = 0x805, -}; - -struct golan_inbox_hdr { - __be16 opcode; - u8 rsvd[4]; - __be16 opmod; -} __attribute ( ( packed ) ); - -struct golan_cmd_layout { - u8 type; - u8 rsvd0[3]; - __be32 inlen; - union { - __be64 in_ptr; - __be32 in_ptr32[2]; - }; - __be32 in[4]; - __be32 out[4]; - union { - __be64 out_ptr; - __be32 out_ptr32[2]; - }; - __be32 outlen; - u8 token; - u8 sig; - u8 rsvd1; - volatile u8 status_own; -} __attribute ( ( packed ) ); - -struct golan_outbox_hdr { - u8 status; - u8 rsvd[3]; - __be32 syndrome; -} __attribute ( ( packed ) ); - -enum { - GOLAN_DEV_CAP_FLAG_RC = 1LL << 0, - GOLAN_DEV_CAP_FLAG_UC = 1LL << 1, - GOLAN_DEV_CAP_FLAG_UD = 1LL << 2, - GOLAN_DEV_CAP_FLAG_XRC = 1LL << 3, - GOLAN_DEV_CAP_FLAG_SRQ = 1LL << 6, - GOLAN_DEV_CAP_FLAG_BAD_PKEY_CNTR = 1LL << 8, - GOLAN_DEV_CAP_FLAG_BAD_QKEY_CNTR = 1LL << 9, - GOLAN_DEV_CAP_FLAG_APM = 1LL << 17, - GOLAN_DEV_CAP_FLAG_ATOMIC = 1LL << 18, - GOLAN_DEV_CAP_FLAG_ON_DMND_PG = 1LL << 24, - GOLAN_DEV_CAP_FLAG_RESIZE_SRQ = 1LL << 32, - GOLAN_DEV_CAP_FLAG_REMOTE_FENCE = 1LL << 38, - GOLAN_DEV_CAP_FLAG_TLP_HINTS = 1LL << 39, - GOLAN_DEV_CAP_FLAG_SIG_HAND_OVER = 1LL << 40, - GOLAN_DEV_CAP_FLAG_DCT = 1LL << 41, - GOLAN_DEV_CAP_FLAG_CMDIF_CSUM = 1LL << 46, -}; - - -struct golan_hca_cap { - u8 rsvd1[16]; - u8 log_max_srq_sz; - u8 log_max_qp_sz; - u8 rsvd2; - u8 log_max_qp; - u8 log_max_strq_sz; - u8 log_max_srqs; - u8 rsvd4[2]; - u8 rsvd5; - u8 log_max_cq_sz; - u8 rsvd6; - u8 log_max_cq; - u8 log_max_eq_sz; - u8 log_max_mkey; - u8 rsvd7; - u8 log_max_eq; - u8 max_indirection; - u8 log_max_mrw_sz; - u8 log_max_bsf_list_sz; - u8 log_max_klm_list_sz; - u8 rsvd_8_0; - u8 log_max_ra_req_dc; - u8 rsvd_8_1; - u8 log_max_ra_res_dc; - u8 rsvd9; - u8 log_max_ra_req_qp; - u8 rsvd10; - u8 log_max_ra_res_qp; - u8 rsvd11[4]; - __be16 max_qp_count; - __be16 pkey_table_size; - u8 rsvd13; - u8 local_ca_ack_delay; - u8 rsvd14; - u8 num_ports; - u8 log_max_msg; - u8 rsvd15[3]; - __be16 stat_rate_support; - u8 rsvd16[2]; - __be64 flags; - u8 rsvd17; - u8 uar_sz; - u8 rsvd18; - u8 log_pg_sz; - __be16 bf_log_bf_reg_size; - u8 rsvd19[4]; - __be16 max_wqe_sz_sq; - u8 rsvd20[2]; - __be16 max_wqe_sz_rq; - u8 rsvd21[2]; - __be16 max_wqe_sz_sq_dc; - u8 rsvd22[4]; - __be16 max_qp_mcg; - u8 rsvd23; - u8 log_max_mcg; - u8 rsvd24; - u8 log_max_pd; - u8 rsvd25; - u8 log_max_xrcd; - u8 rsvd26[40]; - __be32 uar_page_sz; - u8 rsvd27[28]; - u8 log_msx_atomic_size_qp; - u8 rsvd28[2]; - u8 log_msx_atomic_size_dc; - u8 rsvd29[76]; -} __attribute ( ( packed ) ); - -struct golan_query_pages_inbox { - struct golan_inbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -struct golan_query_pages_outbox { - struct golan_outbox_hdr hdr; - u8 rsvd[2]; - __be16 func_id; - __be32 num_pages; -} __attribute ( ( packed ) ); - -struct golan_cmd_query_hca_cap_mbox_in { - struct golan_inbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -struct golan_cmd_query_hca_cap_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd0[8]; - struct golan_hca_cap hca_cap; -} __attribute ( ( packed ) ); - -struct golan_cmd_set_hca_cap_mbox_in { - struct golan_inbox_hdr hdr; - u8 rsvd[8]; - struct golan_hca_cap hca_cap; -} __attribute ( ( packed ) ); - -struct golan_cmd_set_hca_cap_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd0[8]; -} __attribute ( ( packed ) ); - -struct golan_cmd_init_hca_mbox_in { - struct golan_inbox_hdr hdr; - u8 rsvd0[2]; - __be16 profile; - u8 rsvd1[4]; -} __attribute ( ( packed ) ); - -struct golan_cmd_init_hca_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -enum golan_teardown { - GOLAN_TEARDOWN_GRACEFUL = 0x0, - GOLAN_TEARDOWN_PANIC = 0x1 -}; - -struct golan_cmd_teardown_hca_mbox_in { - struct golan_inbox_hdr hdr; - u8 rsvd0[2]; - __be16 profile; - u8 rsvd1[4]; -} __attribute ( ( packed ) ); - -struct golan_cmd_teardown_hca_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -struct golan_enable_hca_mbox_in { - struct golan_inbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -struct golan_enable_hca_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -struct golan_disable_hca_mbox_in { - struct golan_inbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -struct golan_disable_hca_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -struct golan_manage_pages_inbox_data { - u8 rsvd2[16]; - __be64 pas[0]; -} __attribute ( ( packed ) ); - -struct golan_manage_pages_inbox { - struct golan_inbox_hdr hdr; - __be16 rsvd0; - __be16 func_id; - __be32 num_entries; - struct golan_manage_pages_inbox_data data; -} __attribute ( ( packed ) ); - -struct golan_manage_pages_outbox_data { - __be64 pas[0]; -} __attribute ( ( packed ) ); - -struct golan_manage_pages_outbox { - struct golan_outbox_hdr hdr; - __be32 num_entries; - __be32 rsrvd; - struct golan_manage_pages_outbox_data data; -} __attribute ( ( packed ) ); - -struct golan_reg_host_endianess { - u8 he; - u8 rsvd[15]; -} __attribute ( ( packed ) ); - -struct golan_cmd_prot_block { - union { - __be64 data[GOLAN_CMD_PAS_CNT]; - u8 bdata[GOLAN_CMD_DATA_BLOCK_SIZE]; - }; - u8 rsvd0[48]; - __be64 next; - __be32 block_num; - u8 rsvd1; - u8 token; - u8 ctrl_sig; - u8 sig; -} __attribute ( ( packed ) ); - -/* MAD IFC structures */ -#define GOLAN_MAD_SIZE 256 -#define GOLAN_MAD_IFC_NO_VALIDATION 0x3 -#define GOLAN_MAD_IFC_RLID_BIT 16 - -struct golan_mad_ifc_mbox_in { - struct golan_inbox_hdr hdr; - __be16 remote_lid; - u8 rsvd0; - u8 port; - u8 rsvd1[4]; - u8 mad[GOLAN_MAD_SIZE]; -} __attribute ( ( packed ) ); - -struct golan_mad_ifc_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; - u8 mad[GOLAN_MAD_SIZE]; -} __attribute ( ( packed ) ); - -/* UAR Structures */ -struct golan_alloc_uar_mbox_in { - struct golan_inbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -struct golan_alloc_uar_mbox_out { - struct golan_outbox_hdr hdr; - __be32 uarn; - u8 rsvd[4]; -} __attribute ( ( packed ) ); - -struct golan_free_uar_mbox_in { - struct golan_inbox_hdr hdr; - __be32 uarn; - u8 rsvd[4]; -} __attribute ( ( packed ) ); - -struct golan_free_uar_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -/* Event Queue Structures */ -enum { - GOLAN_EQ_STATE_ARMED = 0x9, - GOLAN_EQ_STATE_FIRED = 0xa, - GOLAN_EQ_STATE_ALWAYS_ARMED = 0xb, -}; - - -struct golan_eq_context { - u8 status; - u8 ec_oi; - u8 st; - u8 rsvd2[7]; - __be16 page_pffset; - __be32 log_sz_usr_page; - u8 rsvd3[7]; - u8 intr; - u8 log_page_size; - u8 rsvd4[15]; - __be32 consumer_counter; - __be32 produser_counter; - u8 rsvd5[16]; -} __attribute ( ( packed ) ); - -struct golan_create_eq_mbox_in_data { - struct golan_eq_context ctx; - u8 rsvd2[8]; - __be64 events_mask; - u8 rsvd3[176]; - __be64 pas[0]; -} __attribute ( ( packed ) ); - -struct golan_create_eq_mbox_in { - struct golan_inbox_hdr hdr; - u8 rsvd0[3]; - u8 input_eqn; - u8 rsvd1[4]; - struct golan_create_eq_mbox_in_data data; -} __attribute ( ( packed ) ); - -struct golan_create_eq_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd0[3]; - u8 eq_number; - u8 rsvd1[4]; -} __attribute ( ( packed ) ); - -struct golan_destroy_eq_mbox_in { - struct golan_inbox_hdr hdr; - u8 rsvd0[3]; - u8 eqn; - u8 rsvd1[4]; -} __attribute ( ( packed ) ); - -struct golan_destroy_eq_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -/***********************************************/ -/************** Query Vport ****************/ -struct golan_query_hca_vport_context_inbox { - struct golan_inbox_hdr hdr; - __be16 other_vport : 1; - __be16 rsvd1 : 7; - __be16 port_num : 4; - __be16 rsvd2 : 4; - __be16 vport_number; - u8 rsvd[4]; -} __attribute ( ( packed ) ); - -struct golan_query_hca_vport_context_data { - __be32 field_select; - __be32 rsvd1[7]; - //**** - __be16 sm_virt_aware : 1; - __be16 has_smi : 1; - __be16 has_raw : 1; - __be16 grh_required : 1; - __be16 rsvd2 : 12; - u8 port_physical_state : 4; - u8 vport_state_policy : 4; - u8 port_state : 4; - u8 vport_state : 4; - //**** - u8 rsvd3[4]; - //**** - __be32 system_image_guid[2]; - //**** - __be32 port_guid[2]; - //**** - __be32 node_guid[2]; - //**** - __be32 cap_mask1; - __be32 cap_mask1_field_select; - __be32 cap_mask2; - __be32 cap_mask2_field_select; - u8 rsvd4[16]; - __be16 lid; - u8 rsvd5 : 4; - u8 init_type_reply : 4; - u8 lmc : 3; - u8 subnet_timeout : 5; - __be16 sm_lid; - u8 sm_sl : 4; - u8 rsvd6 : 4; - u8 rsvd7; - __be16 qkey_violation_counter; - __be16 pkey_violation_counter; - u8 rsvd8[100]; -} __attribute ( ( packed ) ); - -struct golan_query_hca_vport_context_outbox { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; - struct golan_query_hca_vport_context_data context_data; -} __attribute ( ( packed ) ); - -struct golan_query_hca_vport_gid_inbox { - struct golan_inbox_hdr hdr; - u8 other_vport : 1; - u8 rsvd1 : 7; - u8 port_num : 4; - u8 rsvd2 : 4; - __be16 vport_number; - __be16 rsvd3; - __be16 gid_index; -} __attribute ( ( packed ) ); - -struct golan_query_hca_vport_gid_outbox { - struct golan_outbox_hdr hdr; - u8 rsvd0[4]; - __be16 gids_num; - u8 rsvd1[2]; - __be32 gid0[4]; -} __attribute ( ( packed ) ); - -struct golan_query_hca_vport_pkey_inbox { - struct golan_inbox_hdr hdr; - u8 other_vport : 1; - u8 rsvd1 : 7; - u8 port_num : 4; - u8 rsvd2 : 4; - __be16 vport_number; - __be16 rsvd3; - __be16 pkey_index; -} __attribute ( ( packed ) ); - -struct golan_query_hca_vport_pkey_data { - __be16 rsvd1; - __be16 pkey0; -} __attribute ( ( packed ) ); - -struct golan_query_hca_vport_pkey_outbox { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; - struct golan_query_hca_vport_pkey_data *pkey_data; -} __attribute ( ( packed ) ); - -struct golan_eqe_comp { - __be32 reserved[6]; - __be32 cqn; -} __attribute ( ( packed ) ); - -struct golan_eqe_qp_srq { - __be32 reserved[6]; - __be32 qp_srq_n; -} __attribute ( ( packed ) ); - -struct golan_eqe_cq_err { - __be32 cqn; - u8 reserved1[7]; - u8 syndrome; -} __attribute ( ( packed ) ); - -struct golan_eqe_dropped_packet { -}; - -struct golan_eqe_port_state { - u8 reserved0[8]; - u8 port; -} __attribute ( ( packed ) ); - -struct golan_eqe_gpio { - __be32 reserved0[2]; - __be64 gpio_event; -} __attribute ( ( packed ) ); - -struct golan_eqe_congestion { - u8 type; - u8 rsvd0; - u8 congestion_level; -} __attribute ( ( packed ) ); - -struct golan_eqe_stall_vl { - u8 rsvd0[3]; - u8 port_vl; -} __attribute ( ( packed ) ); - -struct golan_eqe_cmd { - __be32 vector; - __be32 rsvd[6]; -} __attribute ( ( packed ) ); - -struct golan_eqe_page_req { - u8 rsvd0[2]; - __be16 func_id; - u8 rsvd1[2]; - __be16 num_pages; - __be32 rsvd2[5]; -} __attribute ( ( packed ) ); - -union ev_data { - __be32 raw[7]; - struct golan_eqe_cmd cmd; - struct golan_eqe_comp comp; - struct golan_eqe_qp_srq qp_srq; - struct golan_eqe_cq_err cq_err; - struct golan_eqe_dropped_packet dp; - struct golan_eqe_port_state port; - struct golan_eqe_gpio gpio; - struct golan_eqe_congestion cong; - struct golan_eqe_stall_vl stall_vl; - struct golan_eqe_page_req req_pages; -} __attribute__ ((packed)); - -struct golan_eqe { - u8 rsvd0; - u8 type; - u8 rsvd1; - u8 sub_type; - __be32 rsvd2[7]; - union ev_data data; - __be16 rsvd3; - u8 signature; - u8 owner; -} __attribute__ ((packed)); - -/* Protection Domain Structures */ -struct golan_alloc_pd_mbox_in { - struct golan_inbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -struct golan_alloc_pd_mbox_out { - struct golan_outbox_hdr hdr; - __be32 pdn; - u8 rsvd[4]; -} __attribute ( ( packed ) ); - -struct golan_dealloc_pd_mbox_in { - struct golan_inbox_hdr hdr; - __be32 pdn; - u8 rsvd[4]; -} __attribute ( ( packed ) ); - -struct golan_dealloc_pd_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -/* Memory key structures */ -#define GOLAN_IB_ACCESS_LOCAL_READ (1 << 2) -#define GOLAN_IB_ACCESS_LOCAL_WRITE (1 << 3) -#define GOLAN_MKEY_LEN64 (1 << 31) -#define GOLAN_CREATE_MKEY_SEG_QPN_BIT 8 - -struct golan_mkey_seg { - /* - * This is a two bit field occupying bits 31-30. - * bit 31 is always 0, - * bit 30 is zero for regular MRs and 1 (e.g free) for UMRs that do not have tanslation - */ - u8 status; - u8 pcie_control; - u8 flags; - u8 version; - __be32 qpn_mkey7_0; - u8 rsvd1[4]; - __be32 flags_pd; - __be64 start_addr; - __be64 len; - __be32 bsfs_octo_size; - u8 rsvd2[16]; - __be32 xlt_oct_size; - u8 rsvd3[3]; - u8 log2_page_size; - u8 rsvd4[4]; -} __attribute ( ( packed ) ); - -struct golan_create_mkey_mbox_in_data { - struct golan_mkey_seg seg; - u8 rsvd1[16]; - __be32 xlat_oct_act_size; - __be32 bsf_coto_act_size; - u8 rsvd2[168]; - __be64 pas[0]; -} __attribute ( ( packed ) ); - -struct golan_create_mkey_mbox_in { - struct golan_inbox_hdr hdr; - __be32 input_mkey_index; - u8 rsvd0[4]; - struct golan_create_mkey_mbox_in_data data; -} __attribute ( ( packed ) ); - -struct golan_create_mkey_mbox_out { - struct golan_outbox_hdr hdr; - __be32 mkey; - u8 rsvd[4]; -} __attribute ( ( packed ) ); - -struct golan_destroy_mkey_mbox_in { - struct golan_inbox_hdr hdr; - __be32 mkey; - u8 rsvd[4]; -} __attribute ( ( packed ) ); - -struct golan_destroy_mkey_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd[8]; -} __attribute ( ( packed ) ); - -/* Completion Queue Structures */ -enum { - GOLAN_CQ_STATE_ARMED = 9, - GOLAN_CQ_STATE_ALWAYS_ARMED = 0xb, - GOLAN_CQ_STATE_FIRED = 0xa -}; - -enum { - GOLAN_CQE_REQ = 0, - GOLAN_CQE_RESP_WR_IMM = 1, - GOLAN_CQE_RESP_SEND = 2, - GOLAN_CQE_RESP_SEND_IMM = 3, - GOLAN_CQE_RESP_SEND_INV = 4, - GOLAN_CQE_RESIZE_CQ = 0xff, /* TBD */ - GOLAN_CQE_REQ_ERR = 13, - GOLAN_CQE_RESP_ERR = 14 -}; - -struct golan_cq_context { - u8 status; - u8 cqe_sz_flags; - u8 st; - u8 rsvd3; - u8 rsvd4[6]; - __be16 page_offset; - __be32 log_sz_usr_page; - __be16 cq_period; - __be16 cq_max_count; - __be16 rsvd20; - __be16 c_eqn; - u8 log_pg_sz; - u8 rsvd25[7]; - __be32 last_notified_index; - __be32 solicit_producer_index; - __be32 consumer_counter; - __be32 producer_counter; - u8 rsvd48[8]; - __be64 db_record_addr; -} __attribute ( ( packed ) ); - - -struct golan_create_cq_mbox_in_data { - struct golan_cq_context ctx; - u8 rsvd6[192]; - __be64 pas[0]; -} __attribute ( ( packed ) ); - -struct golan_create_cq_mbox_in { - struct golan_inbox_hdr hdr; - __be32 input_cqn; - u8 rsvdx[4]; - struct golan_create_cq_mbox_in_data data; -} __attribute ( ( packed ) ); - -struct golan_create_cq_mbox_out { - struct golan_outbox_hdr hdr; - __be32 cqn; - u8 rsvd0[4]; -} __attribute ( ( packed ) ); - -struct golan_destroy_cq_mbox_in { - struct golan_inbox_hdr hdr; - __be32 cqn; - u8 rsvd0[4]; -} __attribute ( ( packed ) ); - -struct golan_destroy_cq_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd0[8]; -} __attribute ( ( packed ) ); - -struct golan_err_cqe { - u8 rsvd0[32]; - __be32 srqn; - u8 rsvd1[16]; - u8 hw_syndrom; - u8 rsvd2; - u8 vendor_err_synd; - u8 syndrome; - __be32 s_wqe_opcode_qpn; - __be16 wqe_counter; - u8 signature; - u8 op_own; -} __attribute ( ( packed ) ); - -struct golan_cqe64 { - u8 rsvd0[17]; - u8 ml_path; - u8 rsvd20[4]; - __be16 slid; - __be32 flags_rqpn; - u8 rsvd28[4]; - __be32 srqn; - __be32 imm_inval_pkey; - u8 rsvd40[4]; - __be32 byte_cnt; - __be64 timestamp; - __be32 sop_drop_qpn; - __be16 wqe_counter; - u8 signature; - u8 op_own; -} __attribute ( ( packed ) ); - -/* Queue Pair Structures */ -#define GOLAN_QP_CTX_ST_BIT 16 -#define GOLAN_QP_CTX_PM_STATE_BIT 11 -#define GOLAN_QP_CTX_FRE_BIT 11 -#define GOLAN_QP_CTX_RLKY_BIT 4 -#define GOLAN_QP_CTX_RQ_SIZE_BIT 3 -#define GOLAN_QP_CTX_SQ_SIZE_BIT 11 -#define GOLAN_QP_CTX_MTU_BIT 5 -#define GOLAN_QP_CTX_ACK_REQ_FREQ_BIT 28 - -enum { - GOLAN_QP_CTX_DONT_USE_RSRVD_LKEY = 0, - GOLAN_QP_CTX_USE_RSRVD_LKEY = 1 -}; - -enum { - GOLAN_IB_ACK_REQ_FREQ = 8, -}; - -enum golan_qp_optpar { - GOLAN_QP_PARAM_ALT_ADDR_PATH = 1 << 0, - GOLAN_QP_PARAM_RRE = 1 << 1, - GOLAN_QP_PARAM_RAE = 1 << 2, - GOLAN_QP_PARAM_RWE = 1 << 3, - GOLAN_QP_PARAM_PKEY_INDEX = 1 << 4, - GOLAN_QP_PARAM_Q_KEY = 1 << 5, - GOLAN_QP_PARAM_RNR_TIMEOUT = 1 << 6, - GOLAN_QP_PARAM_PRIMARY_ADDR_PATH = 1 << 7, - GOLAN_QP_PARAM_SRA_MAX = 1 << 8, - GOLAN_QP_PARAM_RRA_MAX = 1 << 9, - GOLAN_QP_PARAM_PM_STATE = 1 << 10, - GOLAN_QP_PARAM_RETRY_COUNT = 1 << 12, - GOLAN_QP_PARAM_RNR_RETRY = 1 << 13, - GOLAN_QP_PARAM_ACK_TIMEOUT = 1 << 14, - GOLAN_QP_PARAM_PRI_PORT = 1 << 16, - GOLAN_QP_PARAM_SRQN = 1 << 18, - GOLAN_QP_PARAM_CQN_RCV = 1 << 19, - GOLAN_QP_PARAM_DC_HS = 1 << 20, - GOLAN_QP_PARAM_DC_KEY = 1 << 21 -}; - -#define GOLAN_QP_PARAMS_INIT2RTR_MASK (GOLAN_QP_PARAM_PKEY_INDEX |\ - GOLAN_QP_PARAM_Q_KEY |\ - GOLAN_QP_PARAM_RWE |\ - GOLAN_QP_PARAM_RRE) - -#define GOLAN_QP_PARAMS_RTR2RTS_MASK (GOLAN_QP_PARAM_PM_STATE |\ - GOLAN_QP_PARAM_RNR_TIMEOUT |\ - GOLAN_QP_PARAM_Q_KEY |\ - GOLAN_QP_PARAM_RWE |\ - GOLAN_QP_PARAM_RRE) - - -enum { - GOLAN_QP_ST_RC = 0x0, - GOLAN_QP_ST_UC = 0x1, - GOLAN_QP_ST_UD = 0x2, - GOLAN_QP_ST_XRC = 0x3, - GOLAN_QP_ST_MLX = 0x4, - GOLAN_QP_ST_DC = 0x5, - GOLAN_QP_ST_QP0 = 0x7, - GOLAN_QP_ST_QP1 = 0x8, - GOLAN_QP_ST_RAW_ETHERTYPE = 0x9, - GOLAN_QP_ST_RAW_IPV6 = 0xa, - GOLAN_QP_ST_SNIFFER = 0xb, - GOLAN_QP_ST_SYNC_UMR = 0xe, - GOLAN_QP_ST_PTP_1588 = 0xd, - GOLAN_QP_ST_REG_UMR = 0xc, - GOLAN_QP_ST_MAX -}; - -enum { - GOLAN_QP_PM_MIGRATED = 0x3, - GOLAN_QP_PM_ARMED = 0x0, - GOLAN_QP_PM_REARM = 0x1 -}; - -enum { - GOLAN_QP_LAT_SENSITIVE = 1 << 28, - GOLAN_QP_ENABLE_SIG = 1 << 31 -}; - - -struct golan_qp_db { - u8 rsvd0[2]; - __be16 recv_db; - u8 rsvd1[2]; - __be16 send_db; -} __attribute ( ( packed ) ); - -enum { - GOLAN_WQE_CTRL_CQ_UPDATE = 2 << 2, /*Wissam, wtf?*/ - GOLAN_WQE_CTRL_SOLICITED = 1 << 1 -}; - -struct golan_wqe_ctrl_seg { - __be32 opmod_idx_opcode; - __be32 qpn_ds; - u8 signature; - u8 rsvd[2]; - u8 fm_ce_se; - __be32 imm; -} __attribute ( ( packed ) ); - -struct golan_av { - union { - struct { - __be32 qkey; - __be32 reserved; - } qkey; - __be64 dc_key; - } key; - __be32 dqp_dct; - u8 stat_rate_sl; - u8 fl_mlid; - __be16 rlid; - u8 reserved0[10]; - u8 tclass; - u8 hop_limit; - __be32 grh_gid_fl; - u8 rgid[16]; -} __attribute ( ( packed ) ); - -struct golan_wqe_data_seg { - __be32 byte_count; - __be32 lkey; - __be64 addr; -} __attribute ( ( packed ) ); - -struct golan_wqe_signature_seg { - u8 rsvd0[4]; - u8 signature; - u8 rsvd1[11]; -} __attribute ( ( packed ) ); - -struct golan_wqe_inline_seg { - __be32 byte_count; -} __attribute ( ( packed ) ); - -struct golan_qp_path { - u8 fl; - u8 rsvd3; - u8 free_ar; - u8 pkey_index; - u8 rsvd0; - u8 grh_mlid; - __be16 rlid; - u8 ackto_lt; - u8 mgid_index; - u8 static_rate; - u8 hop_limit; - __be32 tclass_flowlabel; - u8 rgid[16]; - u8 rsvd1[4]; - u8 sl; - u8 port; - u8 rsvd2[6]; -} __attribute ( ( packed ) ); - -struct golan_qp_context { - __be32 flags; - __be32 flags_pd; - u8 mtu_msgmax; - u8 rq_size_stride; - __be16 sq_crq_size; - __be32 qp_counter_set_usr_page; - __be32 wire_qpn; - __be32 log_pg_sz_remote_qpn; - struct golan_qp_path pri_path; - struct golan_qp_path alt_path; - __be32 params1; - u8 reserved2[4]; - __be32 next_send_psn; - __be32 cqn_send; - u8 reserved3[8]; - __be32 last_acked_psn; - __be32 ssn; - __be32 params2; - __be32 rnr_nextrecvpsn; - __be32 xrcd; - __be32 cqn_recv; - __be64 db_rec_addr; - __be32 qkey; - __be32 rq_type_srqn; - __be32 rmsn; - __be16 hw_sq_wqe_counter; - __be16 sw_sq_wqe_counter; - __be16 hw_rcyclic_byte_counter; - __be16 hw_rq_counter; - __be16 sw_rcyclic_byte_counter; - __be16 sw_rq_counter; - u8 rsvd0[5]; - u8 cgs; - u8 cs_req; - u8 cs_res; - __be64 dc_access_key; - u8 rsvd1[24]; -} __attribute ( ( packed ) ); - -struct golan_create_qp_mbox_in_data { - __be32 opt_param_mask; - u8 rsvd1[4]; - struct golan_qp_context ctx; - u8 rsvd3[16]; - __be64 pas[0]; -} __attribute ( ( packed ) ); - -struct golan_create_qp_mbox_in { - struct golan_inbox_hdr hdr; - __be32 input_qpn; - u8 rsvd0[4]; - struct golan_create_qp_mbox_in_data data; -} __attribute ( ( packed ) ); - -struct golan_create_qp_mbox_out { - struct golan_outbox_hdr hdr; - __be32 qpn; - u8 rsvd0[4]; -} __attribute ( ( packed ) ); - -struct golan_destroy_qp_mbox_in { - struct golan_inbox_hdr hdr; - __be32 qpn; - u8 rsvd0[4]; -} __attribute ( ( packed ) ); - -struct golan_destroy_qp_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd0[8]; -} __attribute ( ( packed ) ); - -struct golan_modify_qp_mbox_in_data { - __be32 optparam; - u8 rsvd0[4]; - struct golan_qp_context ctx; -} __attribute ( ( packed ) ); - -struct golan_modify_qp_mbox_in { - struct golan_inbox_hdr hdr; - __be32 qpn; - u8 rsvd1[4]; - struct golan_modify_qp_mbox_in_data data; -} __attribute ( ( packed ) ); - -struct golan_modify_qp_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvd0[8]; -} __attribute ( ( packed ) ); - -struct golan_attach_mcg_mbox_in { - struct golan_inbox_hdr hdr; - __be32 qpn; - __be32 rsvd; - u8 gid[16]; -} __attribute ( ( packed ) ); - -struct golan_attach_mcg_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvf[8]; -} __attribute ( ( packed ) ); - -struct golan_detach_mcg_mbox_in { - struct golan_inbox_hdr hdr; - __be32 qpn; - __be32 rsvd; - u8 gid[16]; -} __attribute ( ( packed ) ); - -struct golan_detach_mcg_mbox_out { - struct golan_outbox_hdr hdr; - u8 rsvf[8]; -} __attribute ( ( packed ) ); - - -#define MAILBOX_SIZE sizeof(struct golan_cmd_prot_block) - -#endif /* __CIB_PRM__ */ diff --git a/roms/ipxe/src/drivers/infiniband/arbel.c b/roms/ipxe/src/drivers/infiniband/arbel.c index 9671174c3..2a6c32dec 100644 --- a/roms/ipxe/src/drivers/infiniband/arbel.c +++ b/roms/ipxe/src/drivers/infiniband/arbel.c @@ -897,44 +897,26 @@ static int arbel_create_send_wq ( struct arbel_send_work_queue *arbel_send_wq, * * @v arbel_recv_wq Receive work queue * @v num_wqes Number of work queue entries - * @v type Queue pair type * @ret rc Return status code */ static int arbel_create_recv_wq ( struct arbel_recv_work_queue *arbel_recv_wq, - unsigned int num_wqes, - enum ib_queue_pair_type type ) { + unsigned int num_wqes ) { struct arbelprm_recv_wqe *wqe; struct arbelprm_recv_wqe *next_wqe; unsigned int wqe_idx_mask; size_t nds; unsigned int i; unsigned int j; - int rc; /* Allocate work queue */ arbel_recv_wq->wqe_size = ( num_wqes * sizeof ( arbel_recv_wq->wqe[0] ) ); arbel_recv_wq->wqe = malloc_dma ( arbel_recv_wq->wqe_size, sizeof ( arbel_recv_wq->wqe[0] ) ); - if ( ! arbel_recv_wq->wqe ) { - rc = -ENOMEM; - goto err_alloc_wqe; - } + if ( ! arbel_recv_wq->wqe ) + return -ENOMEM; memset ( arbel_recv_wq->wqe, 0, arbel_recv_wq->wqe_size ); - /* Allocate GRH entries, if needed */ - if ( ( type == IB_QPT_SMI ) || ( type == IB_QPT_GSI ) || - ( type == IB_QPT_UD ) ) { - arbel_recv_wq->grh_size = ( num_wqes * - sizeof ( arbel_recv_wq->grh[0] ) ); - arbel_recv_wq->grh = malloc_dma ( arbel_recv_wq->grh_size, - sizeof ( void * ) ); - if ( ! arbel_recv_wq->grh ) { - rc = -ENOMEM; - goto err_alloc_grh; - } - } - /* Link work queue entries */ wqe_idx_mask = ( num_wqes - 1 ); nds = ( ( offsetof ( typeof ( *wqe ), data ) + @@ -953,12 +935,6 @@ static int arbel_create_recv_wq ( struct arbel_recv_work_queue *arbel_recv_wq, } return 0; - - free_dma ( arbel_recv_wq->grh, arbel_recv_wq->grh_size ); - err_alloc_grh: - free_dma ( arbel_recv_wq->wqe, arbel_recv_wq->wqe_size ); - err_alloc_wqe: - return rc; } /** @@ -1009,8 +985,8 @@ static int arbel_create_qp ( struct ib_device *ibdev, if ( ( rc = arbel_create_send_wq ( &arbel_qp->send, qp->send.num_wqes ) ) != 0 ) goto err_create_send_wq; - if ( ( rc = arbel_create_recv_wq ( &arbel_qp->recv, qp->recv.num_wqes, - qp->type ) ) != 0 ) + if ( ( rc = arbel_create_recv_wq ( &arbel_qp->recv, + qp->recv.num_wqes ) ) != 0 ) goto err_create_recv_wq; /* Send and receive work queue entries must be within the same 4GB */ @@ -1102,7 +1078,6 @@ static int arbel_create_qp ( struct ib_device *ibdev, MLX_FILL_1 ( send_db_rec, 1, res, ARBEL_UAR_RES_NONE ); MLX_FILL_1 ( recv_db_rec, 1, res, ARBEL_UAR_RES_NONE ); err_unsupported_address_split: - free_dma ( arbel_qp->recv.grh, arbel_qp->recv.grh_size ); free_dma ( arbel_qp->recv.wqe, arbel_qp->recv.wqe_size ); err_create_recv_wq: free_dma ( arbel_qp->send.wqe, arbel_qp->send.wqe_size ); @@ -1231,9 +1206,8 @@ static void arbel_destroy_qp ( struct ib_device *ibdev, MLX_FILL_1 ( recv_db_rec, 1, res, ARBEL_UAR_RES_NONE ); /* Free memory */ - free_dma ( arbel_qp->recv.grh, arbel_qp->recv.grh_size ); - free_dma ( arbel_qp->recv.wqe, arbel_qp->recv.wqe_size ); free_dma ( arbel_qp->send.wqe, arbel_qp->send.wqe_size ); + free_dma ( arbel_qp->recv.wqe, arbel_qp->recv.wqe_size ); free ( arbel_qp ); /* Mark queue number as free */ @@ -1503,8 +1477,6 @@ static int arbel_post_recv ( struct ib_device *ibdev, struct ib_work_queue *wq = &qp->recv; struct arbel_recv_work_queue *arbel_recv_wq = &arbel_qp->recv; struct arbelprm_recv_wqe *wqe; - struct arbelprm_wqe_segment_data_ptr *data; - struct ib_global_route_header *grh; union arbelprm_doorbell_record *db_rec; unsigned int wqe_idx_mask; @@ -1519,19 +1491,12 @@ static int arbel_post_recv ( struct ib_device *ibdev, wqe = &arbel_recv_wq->wqe[wq->next_idx & wqe_idx_mask].recv; /* Construct work queue entry */ - data = &wqe->data[0]; - if ( arbel_recv_wq->grh ) { - grh = &arbel_recv_wq->grh[wq->next_idx & wqe_idx_mask]; - MLX_FILL_1 ( data, 0, byte_count, sizeof ( *grh ) ); - MLX_FILL_1 ( data, 1, l_key, arbel->lkey ); - MLX_FILL_H ( data, 2, local_address_h, virt_to_bus ( grh ) ); - MLX_FILL_1 ( data, 3, local_address_l, virt_to_bus ( grh ) ); - data++; - } - MLX_FILL_1 ( data, 0, byte_count, iob_tailroom ( iobuf ) ); - MLX_FILL_1 ( data, 1, l_key, arbel->lkey ); - MLX_FILL_H ( data, 2, local_address_h, virt_to_bus ( iobuf->data ) ); - MLX_FILL_1 ( data, 3, local_address_l, virt_to_bus ( iobuf->data ) ); + MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) ); + MLX_FILL_1 ( &wqe->data[0], 1, l_key, arbel->lkey ); + MLX_FILL_H ( &wqe->data[0], 2, + local_address_h, virt_to_bus ( iobuf->data ) ); + MLX_FILL_1 ( &wqe->data[0], 3, + local_address_l, virt_to_bus ( iobuf->data ) ); /* Update doorbell record */ barrier(); @@ -1646,16 +1611,17 @@ static int arbel_complete ( struct ib_device *ibdev, MLX_FILL_1 ( &recv_wqe->data[0], 0, byte_count, 0 ); MLX_FILL_1 ( &recv_wqe->data[0], 1, l_key, ARBEL_INVALID_LKEY ); + assert ( len <= iob_tailroom ( iobuf ) ); + iob_put ( iobuf, len ); memset ( &recv_dest, 0, sizeof ( recv_dest ) ); recv_dest.qpn = qpn; switch ( qp->type ) { case IB_QPT_SMI: case IB_QPT_GSI: case IB_QPT_UD: - /* Locate corresponding GRH */ - assert ( arbel_recv_wq->grh != NULL ); - grh = &arbel_recv_wq->grh[wqe_idx]; - len -= sizeof ( *grh ); + assert ( iob_len ( iobuf ) >= sizeof ( *grh ) ); + grh = iobuf->data; + iob_pull ( iobuf, sizeof ( *grh ) ); /* Construct address vector */ source = &recv_source; memset ( source, 0, sizeof ( *source ) ); @@ -1676,8 +1642,6 @@ static int arbel_complete ( struct ib_device *ibdev, assert ( 0 ); return -EINVAL; } - assert ( len <= iob_tailroom ( iobuf ) ); - iob_put ( iobuf, len ); /* Hand off to completion handler */ ib_complete_recv ( ibdev, qp, &recv_dest, source, iobuf, rc ); } @@ -3036,16 +3000,6 @@ static int arbel_probe ( struct pci_device *pci ) { pci_set_drvdata ( pci, arbel ); arbel->pci = pci; - /* Fix up PCI device */ - adjust_pci_device ( pci ); - - /* Map PCI BARs */ - arbel->config = ioremap ( pci_bar_start ( pci, ARBEL_PCI_CONFIG_BAR ), - ARBEL_PCI_CONFIG_BAR_SIZE ); - arbel->uar = ioremap ( ( pci_bar_start ( pci, ARBEL_PCI_UAR_BAR ) + - ARBEL_PCI_UAR_IDX * ARBEL_PCI_UAR_SIZE ), - ARBEL_PCI_UAR_SIZE ); - /* Allocate Infiniband devices */ for ( i = 0 ; i < ARBEL_NUM_PORTS ; i++ ) { ibdev = alloc_ibdev ( 0 ); @@ -3060,6 +3014,16 @@ static int arbel_probe ( struct pci_device *pci ) { ib_set_drvdata ( ibdev, arbel ); } + /* Fix up PCI device */ + adjust_pci_device ( pci ); + + /* Get PCI BARs */ + arbel->config = ioremap ( pci_bar_start ( pci, ARBEL_PCI_CONFIG_BAR ), + ARBEL_PCI_CONFIG_BAR_SIZE ); + arbel->uar = ioremap ( ( pci_bar_start ( pci, ARBEL_PCI_UAR_BAR ) + + ARBEL_PCI_UAR_IDX * ARBEL_PCI_UAR_SIZE ), + ARBEL_PCI_UAR_SIZE ); + /* Reset device */ arbel_reset ( arbel ); @@ -3108,8 +3072,6 @@ static int arbel_probe ( struct pci_device *pci ) { err_alloc_ibdev: for ( i-- ; i >= 0 ; i-- ) ibdev_put ( arbel->ibdev[i] ); - iounmap ( arbel->uar ); - iounmap ( arbel->config ); arbel_free ( arbel ); err_alloc: return rc; @@ -3128,8 +3090,6 @@ static void arbel_remove ( struct pci_device *pci ) { unregister_ibdev ( arbel->ibdev[i] ); for ( i = ( ARBEL_NUM_PORTS - 1 ) ; i >= 0 ; i-- ) ibdev_put ( arbel->ibdev[i] ); - iounmap ( arbel->uar ); - iounmap ( arbel->config ); arbel_free ( arbel ); } diff --git a/roms/ipxe/src/drivers/infiniband/arbel.h b/roms/ipxe/src/drivers/infiniband/arbel.h index 8a5a996a3..73394cd9a 100644 --- a/roms/ipxe/src/drivers/infiniband/arbel.h +++ b/roms/ipxe/src/drivers/infiniband/arbel.h @@ -237,7 +237,7 @@ struct arbelprm_rc_send_wqe { struct arbelprm_wqe_segment_data_ptr data[ARBEL_MAX_GATHER]; } __attribute__ (( packed )); -#define ARBEL_MAX_SCATTER 2 +#define ARBEL_MAX_SCATTER 1 struct arbelprm_recv_wqe { /* The autogenerated header is inconsistent between send and @@ -369,10 +369,6 @@ struct arbel_recv_work_queue { union arbel_recv_wqe *wqe; /** Size of work queue */ size_t wqe_size; - /** GRH buffers (if applicable) */ - struct ib_global_route_header *grh; - /** Size of GRB buffers */ - size_t grh_size; }; /** Number of special queue pairs */ diff --git a/roms/ipxe/src/drivers/infiniband/flexboot_nodnic.c b/roms/ipxe/src/drivers/infiniband/flexboot_nodnic.c deleted file mode 100644 index dea19ca69..000000000 --- a/roms/ipxe/src/drivers/infiniband/flexboot_nodnic.c +++ /dev/null @@ -1,1479 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stdio.h> -#include <unistd.h> -#include <errno.h> -#include <byteswap.h> -#include <ipxe/pci.h> -#include <ipxe/malloc.h> -#include <ipxe/umalloc.h> -#include <ipxe/if_ether.h> -#include <ipxe/ethernet.h> -#include <ipxe/vlan.h> -#include <ipxe/io.h> -#include "flexboot_nodnic.h" -#include "mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig.h" -#include "mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_defaults.h" -#include "mlx_utils/include/public/mlx_pci_gw.h" -#include "mlx_utils/mlx_lib/mlx_vmac/mlx_vmac.h" -#include "mlx_utils/include/public/mlx_types.h" -#include "mlx_utils/include/public/mlx_utils.h" -#include "mlx_utils/include/public/mlx_bail.h" -#include "mlx_nodnic/include/mlx_cmd.h" -#include "mlx_utils/include/public/mlx_memory.h" -#include "mlx_utils/include/public/mlx_pci.h" -#include "mlx_nodnic/include/mlx_device.h" -#include "mlx_nodnic/include/mlx_port.h" - -/*************************************************************************** - * - * Completion queue operations - * - *************************************************************************** - */ -static int flexboot_nodnic_arm_cq ( struct flexboot_nodnic_port *port ) { -#ifndef DEVICE_CX3 - mlx_uint32 val = ( port->eth_cq->next_idx & 0xffff ); - if ( nodnic_port_set ( & port->port_priv, nodnic_port_option_arm_cq, val ) ) { - MLX_DEBUG_ERROR( port->port_priv.device, "Failed to arm the CQ\n" ); - return MLX_FAILED; - } -#else - mlx_utils *utils = port->port_priv.device->utils; - nodnic_port_data_flow_gw *ptr = port->port_priv.data_flow_gw; - mlx_uint32 data = 0; - mlx_uint32 val = 0; - - if ( port->port_priv.device->device_cap.crspace_doorbells == 0 ) { - val = ( port->eth_cq->next_idx & 0xffff ); - if ( nodnic_port_set ( & port->port_priv, nodnic_port_option_arm_cq, val ) ) { - MLX_DEBUG_ERROR( port->port_priv.device, "Failed to arm the CQ\n" ); - return MLX_FAILED; - } - } else { - /* Arming the CQ with CQ CI should be with this format - - * 16 bit - CQ CI - same endianness as the FW (don't swap bytes) - * 15 bit - reserved - * 1 bit - arm CQ - must correct the endianness with the reserved above */ - data = ( ( ( port->eth_cq->next_idx & 0xffff ) << 16 ) | 0x0080 ); - /* Write the new index and update FW that new data was submitted */ - mlx_pci_mem_write ( utils, MlxPciWidthUint32, 0, - ( mlx_uint64 ) & ( ptr->armcq_cq_ci_dword ), 1, &data ); - } -#endif - return 0; -} - -/** - * Create completion queue - * - * @v ibdev Infiniband device - * @v cq Completion queue - * @ret rc Return status code - */ -static int flexboot_nodnic_create_cq ( struct ib_device *ibdev , - struct ib_completion_queue *cq ) { - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1]; - struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq; - mlx_status status = MLX_SUCCESS; - - flexboot_nodnic_cq = (struct flexboot_nodnic_completion_queue *) - zalloc(sizeof(*flexboot_nodnic_cq)); - if ( flexboot_nodnic_cq == NULL ) { - status = MLX_OUT_OF_RESOURCES; - goto qp_alloc_err; - } - - status = nodnic_port_create_cq(&port->port_priv, - cq->num_cqes * - flexboot_nodnic->callbacks->get_cqe_size(), - &flexboot_nodnic_cq->nodnic_completion_queue - ); - MLX_FATAL_CHECK_STATUS(status, create_err, - "nodnic_port_create_cq failed"); - flexboot_nodnic->callbacks->cqe_set_owner( - flexboot_nodnic_cq->nodnic_completion_queue->cq_virt, - cq->num_cqes); - - - ib_cq_set_drvdata ( cq, flexboot_nodnic_cq ); - return status; -create_err: - free(flexboot_nodnic_cq); -qp_alloc_err: - return status; -} - -/** - * Destroy completion queue - * - * @v ibdev Infiniband device - * @v cq Completion queue - */ -static void flexboot_nodnic_destroy_cq ( struct ib_device *ibdev , - struct ib_completion_queue *cq ) { - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1]; - struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq = ib_cq_get_drvdata ( cq ); - - nodnic_port_destroy_cq(&port->port_priv, - flexboot_nodnic_cq->nodnic_completion_queue); - - free(flexboot_nodnic_cq); -} - -static -struct ib_work_queue * flexboot_nodnic_find_wq ( struct ib_device *ibdev , - struct ib_completion_queue *cq, - unsigned long qpn, int is_send ) { - struct ib_work_queue *wq; - struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp; - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1]; - struct nodnic_ring *ring; - mlx_uint32 out_qpn; - list_for_each_entry ( wq, &cq->work_queues, list ) { - flexboot_nodnic_qp = ib_qp_get_drvdata ( wq->qp ); - if( wq->is_send == is_send && wq->is_send == TRUE ) { - ring = &flexboot_nodnic_qp->nodnic_queue_pair->send.nodnic_ring; - } else if( wq->is_send == is_send && wq->is_send == FALSE ) { - ring = &flexboot_nodnic_qp->nodnic_queue_pair->receive.nodnic_ring; - } else { - continue; - } - nodnic_port_get_qpn(&port->port_priv, ring, &out_qpn); - if ( out_qpn == qpn ) - return wq; - } - return NULL; -} - -/** - * Handle completion - * - * @v ibdev Infiniband device - * @v cq Completion queue - * @v cqe Hardware completion queue entry - * @ret rc Return status code - */ -static int flexboot_nodnic_complete ( struct ib_device *ibdev, - struct ib_completion_queue *cq, - struct cqe_data *cqe_data ) { - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct ib_work_queue *wq; - struct ib_queue_pair *qp; - struct io_buffer *iobuf; - struct ib_address_vector recv_dest; - struct ib_address_vector recv_source; - unsigned long qpn; - unsigned long wqe_idx; - unsigned long wqe_idx_mask; - size_t len; - int rc = 0; - - /* Parse completion */ - qpn = cqe_data->qpn; - - if ( cqe_data->is_error == TRUE ) { - DBGC ( flexboot_nodnic, "flexboot_nodnic %p CQN %#lx syndrome %x vendor %x\n", - flexboot_nodnic, cq->cqn, cqe_data->syndrome, - cqe_data->vendor_err_syndrome ); - rc = -EIO; - /* Don't return immediately; propagate error to completer */ - } - - /* Identify work queue */ - wq = flexboot_nodnic_find_wq( ibdev, cq, qpn, cqe_data->is_send ); - if ( wq == NULL ) { - DBGC ( flexboot_nodnic, - "flexboot_nodnic %p CQN %#lx unknown %s QPN %#lx\n", - flexboot_nodnic, cq->cqn, - ( cqe_data->is_send ? "send" : "recv" ), qpn ); - return -EIO; - } - qp = wq->qp; - - /* Identify work queue entry */ - wqe_idx = cqe_data->wqe_counter; - wqe_idx_mask = ( wq->num_wqes - 1 ); - DBGCP ( flexboot_nodnic, - "NODNIC %p CQN %#lx QPN %#lx %s WQE %#lx completed:\n", - flexboot_nodnic, cq->cqn, qp->qpn, - ( cqe_data->is_send ? "send" : "recv" ), - wqe_idx ); - - /* Identify I/O buffer */ - iobuf = wq->iobufs[wqe_idx & wqe_idx_mask]; - if ( iobuf == NULL ) { - DBGC ( flexboot_nodnic, - "NODNIC %p CQN %#lx QPN %#lx empty %s WQE %#lx\n", - flexboot_nodnic, cq->cqn, qp->qpn, - ( cqe_data->is_send ? "send" : "recv" ), wqe_idx ); - return -EIO; - } - wq->iobufs[wqe_idx & wqe_idx_mask] = NULL; - - if ( cqe_data->is_send == TRUE ) { - /* Hand off to completion handler */ - ib_complete_send ( ibdev, qp, iobuf, rc ); - } else if ( rc != 0 ) { - /* Propagate error to receive completion handler */ - ib_complete_recv ( ibdev, qp, NULL, NULL, iobuf, rc ); - } else { - /* Set received length */ - len = cqe_data->byte_cnt; - assert ( len <= iob_tailroom ( iobuf ) ); - iob_put ( iobuf, len ); - memset ( &recv_dest, 0, sizeof ( recv_dest ) ); - recv_dest.qpn = qpn; - memset ( &recv_source, 0, sizeof ( recv_source ) ); - switch ( qp->type ) { - case IB_QPT_SMI: - case IB_QPT_GSI: - case IB_QPT_UD: - case IB_QPT_RC: - break; - case IB_QPT_ETH: - break; - default: - assert ( 0 ); - return -EINVAL; - } - /* Hand off to completion handler */ - ib_complete_recv ( ibdev, qp, &recv_dest, - &recv_source, iobuf, rc ); - } - - return rc; -} -/** - * Poll completion queue - * - * @v ibdev Infiniband device - * @v cq Completion queues - */ -static void flexboot_nodnic_poll_cq ( struct ib_device *ibdev, - struct ib_completion_queue *cq) { - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct flexboot_nodnic_completion_queue *flexboot_nodnic_cq = ib_cq_get_drvdata ( cq ); - void *cqe; - mlx_size cqe_size; - struct cqe_data cqe_data; - unsigned int cqe_idx_mask; - int rc; - - cqe_size = flexboot_nodnic->callbacks->get_cqe_size(); - while ( TRUE ) { - /* Look for completion entry */ - cqe_idx_mask = ( cq->num_cqes - 1 ); - cqe = ((uint8_t *)flexboot_nodnic_cq->nodnic_completion_queue->cq_virt) + - cqe_size * (cq->next_idx & cqe_idx_mask); - - /* TODO: check fill_completion */ - flexboot_nodnic->callbacks->fill_completion(cqe, &cqe_data); - if ( cqe_data.owner ^ - ( ( cq->next_idx & cq->num_cqes ) ? 1 : 0 ) ) { - /* Entry still owned by hardware; end of poll */ - break; - } - /* Handle completion */ - rc = flexboot_nodnic_complete ( ibdev, cq, &cqe_data ); - if ( rc != 0 ) { - DBGC ( flexboot_nodnic, "flexboot_nodnic %p CQN %#lx failed to complete: %s\n", - flexboot_nodnic, cq->cqn, strerror ( rc ) ); - DBGC_HDA ( flexboot_nodnic, virt_to_phys ( cqe ), - cqe, sizeof ( *cqe ) ); - } - - /* Update completion queue's index */ - cq->next_idx++; - } -} -/*************************************************************************** - * - * Queue pair operations - * - *************************************************************************** - */ - - -/** - * Create queue pair - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @ret rc Return status code - */ -static int flexboot_nodnic_create_qp ( struct ib_device *ibdev, - struct ib_queue_pair *qp ) { - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1]; - struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp; - mlx_status status = MLX_SUCCESS; - - flexboot_nodnic_qp = (struct flexboot_nodnic_queue_pair *)zalloc(sizeof(*flexboot_nodnic_qp)); - if ( flexboot_nodnic_qp == NULL ) { - status = MLX_OUT_OF_RESOURCES; - goto qp_alloc_err; - } - - status = nodnic_port_create_qp(&port->port_priv, qp->type, - qp->send.num_wqes * sizeof(struct nodnic_send_wqbb), - qp->send.num_wqes, - qp->recv.num_wqes * sizeof(struct nodnic_recv_wqe), - qp->recv.num_wqes, - &flexboot_nodnic_qp->nodnic_queue_pair); - MLX_FATAL_CHECK_STATUS(status, create_err, - "nodnic_port_create_qp failed"); - ib_qp_set_drvdata ( qp, flexboot_nodnic_qp ); - return status; -create_err: - free(flexboot_nodnic_qp); -qp_alloc_err: - return status; -} - -/** - * Modify queue pair - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @ret rc Return status code - */ -static int flexboot_nodnic_modify_qp ( struct ib_device *ibdev __unused, - struct ib_queue_pair *qp __unused) { - /*not needed*/ - return 0; -} - -/** - * Destroy queue pair - * - * @v ibdev Infiniband device - * @v qp Queue pair - */ -static void flexboot_nodnic_destroy_qp ( struct ib_device *ibdev, - struct ib_queue_pair *qp ) { - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1]; - struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp ); - - nodnic_port_destroy_qp(&port->port_priv, qp->type, - flexboot_nodnic_qp->nodnic_queue_pair); - - free(flexboot_nodnic_qp); -} - -/*************************************************************************** - * - * Work request operations - * - *************************************************************************** - */ - -/** - * Post send work queue entry - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v av Address vector - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int flexboot_nodnic_post_send ( struct ib_device *ibdev, - struct ib_queue_pair *qp, - struct ib_address_vector *av, - struct io_buffer *iobuf) { - - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp ); - struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1]; - struct ib_work_queue *wq = &qp->send; - struct nodnic_send_wqbb *wqbb; - nodnic_qp *nodnic_qp = flexboot_nodnic_qp->nodnic_queue_pair; - struct nodnic_send_ring *send_ring = &nodnic_qp->send; - mlx_status status = MLX_SUCCESS; - unsigned int wqe_idx_mask; - unsigned long wqe_idx; - - if ( ( port->port_priv.dma_state == FALSE ) || - ( port->port_priv.port_state & NODNIC_PORT_DISABLING_DMA ) ) { - DBGC ( flexboot_nodnic, "flexboot_nodnic DMA disabled\n"); - status = -ENETDOWN; - goto post_send_done; - } - - /* Allocate work queue entry */ - wqe_idx = wq->next_idx; - wqe_idx_mask = ( wq->num_wqes - 1 ); - if ( wq->iobufs[wqe_idx & wqe_idx_mask] ) { - DBGC ( flexboot_nodnic, "flexboot_nodnic %p QPN %#lx send queue full\n", - flexboot_nodnic, qp->qpn ); - status = -ENOBUFS; - goto post_send_done; - } - wqbb = &send_ring->wqe_virt[wqe_idx & wqe_idx_mask]; - wq->iobufs[wqe_idx & wqe_idx_mask] = iobuf; - - assert ( flexboot_nodnic->callbacks-> - fill_send_wqe[qp->type] != NULL ); - status = flexboot_nodnic->callbacks-> - fill_send_wqe[qp->type] ( ibdev, qp, av, iobuf, - wqbb, wqe_idx ); - if ( status != 0 ) { - DBGC ( flexboot_nodnic, "flexboot_nodnic %p QPN %#lx fill send wqe failed\n", - flexboot_nodnic, qp->qpn ); - goto post_send_done; - } - - wq->next_idx++; - - status = port->port_priv.send_doorbell ( &port->port_priv, - &send_ring->nodnic_ring, ( mlx_uint16 ) wq->next_idx ); - if ( status != 0 ) { - DBGC ( flexboot_nodnic, "flexboot_nodnic %p ring send doorbell failed\n", flexboot_nodnic ); - } - -post_send_done: - return status; -} - -/** - * Post receive work queue entry - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int flexboot_nodnic_post_recv ( struct ib_device *ibdev, - struct ib_queue_pair *qp, - struct io_buffer *iobuf ) { - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = ib_qp_get_drvdata ( qp ); - struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1]; - struct ib_work_queue *wq = &qp->recv; - nodnic_qp *nodnic_qp = flexboot_nodnic_qp->nodnic_queue_pair; - struct nodnic_recv_ring *recv_ring = &nodnic_qp->receive; - struct nodnic_recv_wqe *wqe; - unsigned int wqe_idx_mask; - mlx_status status = MLX_SUCCESS; - - /* Allocate work queue entry */ - wqe_idx_mask = ( wq->num_wqes - 1 ); - if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) { - DBGC ( flexboot_nodnic, - "flexboot_nodnic %p QPN %#lx receive queue full\n", - flexboot_nodnic, qp->qpn ); - status = -ENOBUFS; - goto post_recv_done; - } - wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf; - wqe = &((struct nodnic_recv_wqe*)recv_ring->wqe_virt)[wq->next_idx & wqe_idx_mask]; - - MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) ); - MLX_FILL_1 ( &wqe->data[0], 1, l_key, flexboot_nodnic->device_priv.lkey ); - MLX_FILL_H ( &wqe->data[0], 2, - local_address_h, virt_to_bus ( iobuf->data ) ); - MLX_FILL_1 ( &wqe->data[0], 3, - local_address_l, virt_to_bus ( iobuf->data ) ); - - wq->next_idx++; - - status = port->port_priv.recv_doorbell ( &port->port_priv, - &recv_ring->nodnic_ring, ( mlx_uint16 ) wq->next_idx ); - if ( status != 0 ) { - DBGC ( flexboot_nodnic, "flexboot_nodnic %p ring receive doorbell failed\n", flexboot_nodnic ); - } -post_recv_done: - return status; -} - -/*************************************************************************** - * - * Event queues - * - *************************************************************************** - */ - -static void flexboot_nodnic_poll_eq ( struct ib_device *ibdev ) { - struct flexboot_nodnic *flexboot_nodnic; - struct flexboot_nodnic_port *port; - struct net_device *netdev; - nodnic_port_state state = 0; - mlx_status status; - - if ( ! ibdev ) { - DBG ( "%s: ibdev = NULL!!!\n", __FUNCTION__ ); - return; - } - - flexboot_nodnic = ib_get_drvdata ( ibdev ); - port = &flexboot_nodnic->port[ibdev->port - 1]; - netdev = port->netdev; - - if ( ! netdev_is_open ( netdev ) ) { - DBG2( "%s: port %d is closed\n", __FUNCTION__, port->ibdev->port ); - return; - } - - /* we don't poll EQ. Just poll link status if it's not active */ - if ( ! netdev_link_ok ( netdev ) ) { - status = nodnic_port_get_state ( &port->port_priv, &state ); - MLX_FATAL_CHECK_STATUS(status, state_err, "nodnic_port_get_state failed"); - - if ( state == nodnic_port_state_active ) { - DBG( "%s: port %d physical link is up\n", __FUNCTION__, - port->ibdev->port ); - port->type->state_change ( flexboot_nodnic, port, 1 ); - } - } -state_err: - return; -} - -/*************************************************************************** - * - * Multicast group operations - * - *************************************************************************** - */ -static int flexboot_nodnic_mcast_attach ( struct ib_device *ibdev, - struct ib_queue_pair *qp, - union ib_gid *gid) { - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1]; - mlx_mac_address mac; - mlx_status status = MLX_SUCCESS; - - switch (qp->type) { - case IB_QPT_ETH: - memcpy(&mac, &gid, sizeof(mac)); - status = nodnic_port_add_mac_filter(&port->port_priv, mac); - MLX_CHECK_STATUS(flexboot_nodnic->device_priv, status, mac_err, - "nodnic_port_add_mac_filter failed"); - break; - default: - break; - } -mac_err: - return status; -} -static void flexboot_nodnic_mcast_detach ( struct ib_device *ibdev, - struct ib_queue_pair *qp, - union ib_gid *gid ) { - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1]; - mlx_mac_address mac; - mlx_status status = MLX_SUCCESS; - - switch (qp->type) { - case IB_QPT_ETH: - memcpy(&mac, &gid, sizeof(mac)); - status = nodnic_port_remove_mac_filter(&port->port_priv, mac); - MLX_CHECK_STATUS(flexboot_nodnic->device_priv, status, mac_err, - "nodnic_port_remove_mac_filter failed"); - break; - default: - break; - } -mac_err: - return; -} -/*************************************************************************** - * - * Infiniband link-layer operations - * - *************************************************************************** - */ - -/** - * Initialise Infiniband link - * - * @v ibdev Infiniband device - * @ret rc Return status code - */ -static int flexboot_nodnic_ib_open ( struct ib_device *ibdev __unused) { - int rc = 0; - - /*TODO: add implementation*/ - return rc; -} - -/** - * Close Infiniband link - * - * @v ibdev Infiniband device - */ -static void flexboot_nodnic_ib_close ( struct ib_device *ibdev __unused) { - /*TODO: add implementation*/ -} - -/** - * Inform embedded subnet management agent of a received MAD - * - * @v ibdev Infiniband device - * @v mad MAD - * @ret rc Return status code - */ -static int flexboot_nodnic_inform_sma ( struct ib_device *ibdev __unused, - union ib_mad *mad __unused) { - /*TODO: add implementation*/ - return 0; -} - -/** flexboot_nodnic Infiniband operations */ -static struct ib_device_operations flexboot_nodnic_ib_operations = { - .create_cq = flexboot_nodnic_create_cq, - .destroy_cq = flexboot_nodnic_destroy_cq, - .create_qp = flexboot_nodnic_create_qp, - .modify_qp = flexboot_nodnic_modify_qp, - .destroy_qp = flexboot_nodnic_destroy_qp, - .post_send = flexboot_nodnic_post_send, - .post_recv = flexboot_nodnic_post_recv, - .poll_cq = flexboot_nodnic_poll_cq, - .poll_eq = flexboot_nodnic_poll_eq, - .open = flexboot_nodnic_ib_open, - .close = flexboot_nodnic_ib_close, - .mcast_attach = flexboot_nodnic_mcast_attach, - .mcast_detach = flexboot_nodnic_mcast_detach, - .set_port_info = flexboot_nodnic_inform_sma, - .set_pkey_table = flexboot_nodnic_inform_sma, -}; -/*************************************************************************** - * - * - * - *************************************************************************** - */ - -#define FLEX_NODNIC_TX_POLL_TOUT 500000 -#define FLEX_NODNIC_TX_POLL_USLEEP 10 - -static void flexboot_nodnic_complete_all_tx ( struct flexboot_nodnic_port *port ) { - struct ib_device *ibdev = port->ibdev; - struct ib_completion_queue *cq; - struct ib_work_queue *wq; - int keep_polling = 0; - int timeout = FLEX_NODNIC_TX_POLL_TOUT; - - list_for_each_entry ( cq, &ibdev->cqs, list ) { - do { - ib_poll_cq ( ibdev, cq ); - keep_polling = 0; - list_for_each_entry ( wq, &cq->work_queues, list ) { - if ( wq->is_send ) - keep_polling += ( wq->fill > 0 ); - } - udelay ( FLEX_NODNIC_TX_POLL_USLEEP ); - } while ( keep_polling && ( timeout-- > 0 ) ); - } -} - -static void flexboot_nodnic_port_disable_dma ( struct flexboot_nodnic_port *port ) { - nodnic_port_priv *port_priv = & ( port->port_priv ); - mlx_status status; - - if ( ! ( port_priv->port_state & NODNIC_PORT_OPENED ) ) - return; - - port_priv->port_state |= NODNIC_PORT_DISABLING_DMA; - flexboot_nodnic_complete_all_tx ( port ); - if ( ( status = nodnic_port_disable_dma ( port_priv ) ) ) { - MLX_DEBUG_WARN ( port, "Failed to disable DMA %d\n", status ); - } - - port_priv->port_state &= ~NODNIC_PORT_DISABLING_DMA; -} - -/*************************************************************************** - * - * Ethernet operation - * - *************************************************************************** - */ - -/** Number of flexboot_nodnic Ethernet send work queue entries */ -#define FLEXBOOT_NODNIC_ETH_NUM_SEND_WQES 64 - -/** Number of flexboot_nodnic Ethernet receive work queue entries */ -#define FLEXBOOT_NODNIC_ETH_NUM_RECV_WQES 64 -/** flexboot nodnic Ethernet queue pair operations */ -static struct ib_queue_pair_operations flexboot_nodnic_eth_qp_op = { - .alloc_iob = alloc_iob, -}; - -/** - * Transmit packet via flexboot_nodnic Ethernet device - * - * @v netdev Network device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int flexboot_nodnic_eth_transmit ( struct net_device *netdev, - struct io_buffer *iobuf) { - struct flexboot_nodnic_port *port = netdev->priv; - struct ib_device *ibdev = port->ibdev; - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - int rc; - - rc = ib_post_send ( ibdev, port->eth_qp, NULL, iobuf); - /* Transmit packet */ - if ( rc != 0) { - DBGC ( flexboot_nodnic, "NODNIC %p port %d could not transmit: %s\n", - flexboot_nodnic, ibdev->port, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Handle flexboot_nodnic Ethernet device send completion - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void flexboot_nodnic_eth_complete_send ( struct ib_device *ibdev __unused, - struct ib_queue_pair *qp, - struct io_buffer *iobuf, - int rc) { - struct net_device *netdev = ib_qp_get_ownerdata ( qp ); - - netdev_tx_complete_err ( netdev, iobuf, rc ); -} - -/** - * Handle flexboot_nodnic Ethernet device receive completion - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v av Address vector, or NULL - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void flexboot_nodnic_eth_complete_recv ( struct ib_device *ibdev __unused, - struct ib_queue_pair *qp, - struct ib_address_vector *dest __unused, - struct ib_address_vector *source, - struct io_buffer *iobuf, - int rc) { - struct net_device *netdev = ib_qp_get_ownerdata ( qp ); - - if ( rc != 0 ) { - DBG ( "Received packet with error\n" ); - netdev_rx_err ( netdev, iobuf, rc ); - return; - } - - if ( source == NULL ) { - DBG ( "Received packet without address vector\n" ); - netdev_rx_err ( netdev, iobuf, -ENOTTY ); - return; - } - netdev_rx ( netdev, iobuf ); -} - -/** flexboot_nodnic Ethernet device completion operations */ -static struct ib_completion_queue_operations flexboot_nodnic_eth_cq_op = { - .complete_send = flexboot_nodnic_eth_complete_send, - .complete_recv = flexboot_nodnic_eth_complete_recv, -}; - -/** - * Poll flexboot_nodnic Ethernet device - * - * @v netdev Network device - */ -static void flexboot_nodnic_eth_poll ( struct net_device *netdev) { - struct flexboot_nodnic_port *port = netdev->priv; - struct ib_device *ibdev = port->ibdev; - - ib_poll_eq ( ibdev ); -} - -/** - * Open flexboot_nodnic Ethernet device - * - * @v netdev Network device - * @ret rc Return status code - */ -static int flexboot_nodnic_eth_open ( struct net_device *netdev ) { - struct flexboot_nodnic_port *port = netdev->priv; - struct ib_device *ibdev = port->ibdev; - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - mlx_status status = MLX_SUCCESS; - struct ib_completion_queue *dummy_cq = NULL; - struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = NULL; - mlx_uint64 cq_size = 0; - mlx_uint32 qpn = 0; - nodnic_port_state state = nodnic_port_state_down; - - if ( port->port_priv.port_state & NODNIC_PORT_OPENED ) { - DBGC ( flexboot_nodnic, "%s: port %d is already opened\n", - __FUNCTION__, port->ibdev->port ); - return 0; - } - - port->port_priv.port_state |= NODNIC_PORT_OPENED; - - dummy_cq = zalloc ( sizeof ( struct ib_completion_queue ) ); - if ( dummy_cq == NULL ) { - DBGC ( flexboot_nodnic, "%s: Failed to allocate dummy CQ\n", __FUNCTION__ ); - status = MLX_OUT_OF_RESOURCES; - goto err_create_dummy_cq; - } - INIT_LIST_HEAD ( &dummy_cq->work_queues ); - - port->eth_qp = ib_create_qp ( ibdev, IB_QPT_ETH, - FLEXBOOT_NODNIC_ETH_NUM_SEND_WQES, dummy_cq, - FLEXBOOT_NODNIC_ETH_NUM_RECV_WQES, dummy_cq, - &flexboot_nodnic_eth_qp_op, netdev->name ); - if ( !port->eth_qp ) { - DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not create queue pair\n", - flexboot_nodnic, ibdev->port ); - status = MLX_OUT_OF_RESOURCES; - goto err_create_qp; - } - - ib_qp_set_ownerdata ( port->eth_qp, netdev ); - - status = nodnic_port_get_cq_size(&port->port_priv, &cq_size); - MLX_FATAL_CHECK_STATUS(status, get_cq_size_err, - "nodnic_port_get_cq_size failed"); - - port->eth_cq = ib_create_cq ( ibdev, cq_size, - &flexboot_nodnic_eth_cq_op ); - if ( !port->eth_cq ) { - DBGC ( flexboot_nodnic, - "flexboot_nodnic %p port %d could not create completion queue\n", - flexboot_nodnic, ibdev->port ); - status = MLX_OUT_OF_RESOURCES; - goto err_create_cq; - } - port->eth_qp->send.cq = port->eth_cq; - list_del(&port->eth_qp->send.list); - list_add ( &port->eth_qp->send.list, &port->eth_cq->work_queues ); - port->eth_qp->recv.cq = port->eth_cq; - list_del(&port->eth_qp->recv.list); - list_add ( &port->eth_qp->recv.list, &port->eth_cq->work_queues ); - - status = nodnic_port_allocate_eq(&port->port_priv, - flexboot_nodnic->device_priv.device_cap.log_working_buffer_size); - MLX_FATAL_CHECK_STATUS(status, eq_alloc_err, - "nodnic_port_allocate_eq failed"); - - status = nodnic_port_init(&port->port_priv); - MLX_FATAL_CHECK_STATUS(status, init_err, - "nodnic_port_init failed"); - - /* update qp - qpn */ - flexboot_nodnic_qp = ib_qp_get_drvdata ( port->eth_qp ); - status = nodnic_port_get_qpn(&port->port_priv, - &flexboot_nodnic_qp->nodnic_queue_pair->send.nodnic_ring, - &qpn); - MLX_FATAL_CHECK_STATUS(status, qpn_err, - "nodnic_port_get_qpn failed"); - port->eth_qp->qpn = qpn; - - /* Fill receive rings */ - ib_refill_recv ( ibdev, port->eth_qp ); - - status = nodnic_port_enable_dma(&port->port_priv); - MLX_FATAL_CHECK_STATUS(status, dma_err, - "nodnic_port_enable_dma failed"); - - if (flexboot_nodnic->device_priv.device_cap.support_promisc_filter) { - status = nodnic_port_set_promisc(&port->port_priv, TRUE); - MLX_FATAL_CHECK_STATUS(status, promisc_err, - "nodnic_port_set_promisc failed"); - } - - status = nodnic_port_get_state(&port->port_priv, &state); - MLX_FATAL_CHECK_STATUS(status, state_err, - "nodnic_port_get_state failed"); - - port->type->state_change ( - flexboot_nodnic, port, state == nodnic_port_state_active ); - - DBGC ( flexboot_nodnic, "%s: port %d opened (link is %s)\n", - __FUNCTION__, port->ibdev->port, - ( ( state == nodnic_port_state_active ) ? "Up" : "Down" ) ); - - free(dummy_cq); - return 0; -state_err: -promisc_err: -dma_err: -qpn_err: - nodnic_port_close(&port->port_priv); -init_err: - nodnic_port_free_eq(&port->port_priv); -eq_alloc_err: -err_create_cq: -get_cq_size_err: - ib_destroy_qp(ibdev, port->eth_qp ); -err_create_qp: - free(dummy_cq); -err_create_dummy_cq: - port->port_priv.port_state &= ~NODNIC_PORT_OPENED; - return status; -} - -/** - * Close flexboot_nodnic Ethernet device - * - * @v netdev Network device - */ -static void flexboot_nodnic_eth_close ( struct net_device *netdev) { - struct flexboot_nodnic_port *port = netdev->priv; - struct ib_device *ibdev = port->ibdev; - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - mlx_status status = MLX_SUCCESS; - - if ( ! ( port->port_priv.port_state & NODNIC_PORT_OPENED ) ) { - DBGC ( flexboot_nodnic, "%s: port %d is already closed\n", - __FUNCTION__, port->ibdev->port ); - return; - } - - if (flexboot_nodnic->device_priv.device_cap.support_promisc_filter) { - if ( ( status = nodnic_port_set_promisc( &port->port_priv, FALSE ) ) ) { - DBGC ( flexboot_nodnic, - "nodnic_port_set_promisc failed (status = %d)\n", status ); - } - } - - flexboot_nodnic_port_disable_dma ( port ); - - port->port_priv.port_state &= ~NODNIC_PORT_OPENED; - - port->type->state_change ( flexboot_nodnic, port, FALSE ); - - /* Close port */ - status = nodnic_port_close(&port->port_priv); - if ( status != MLX_SUCCESS ) { - DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not close port: %s\n", - flexboot_nodnic, ibdev->port, strerror ( status ) ); - /* Nothing we can do about this */ - } - - ib_destroy_qp ( ibdev, port->eth_qp ); - port->eth_qp = NULL; - ib_destroy_cq ( ibdev, port->eth_cq ); - port->eth_cq = NULL; - - nodnic_port_free_eq(&port->port_priv); - - DBGC ( flexboot_nodnic, "%s: port %d closed\n", __FUNCTION__, port->ibdev->port ); -} - -void flexboot_nodnic_eth_irq ( struct net_device *netdev, int enable ) { - struct flexboot_nodnic_port *port = netdev->priv; - - if ( enable ) { - if ( ( port->port_priv.port_state & NODNIC_PORT_OPENED ) && - ! ( port->port_priv.port_state & NODNIC_PORT_DISABLING_DMA ) ) { - flexboot_nodnic_arm_cq ( port ); - } else { - /* do nothing */ - } - } else { - nodnic_device_clear_int( port->port_priv.device ); - } -} - -/** flexboot_nodnic Ethernet network device operations */ -static struct net_device_operations flexboot_nodnic_eth_operations = { - .open = flexboot_nodnic_eth_open, - .close = flexboot_nodnic_eth_close, - .transmit = flexboot_nodnic_eth_transmit, - .poll = flexboot_nodnic_eth_poll, -}; - -/** - * Register flexboot_nodnic Ethernet device - */ -static int flexboot_nodnic_register_netdev ( struct flexboot_nodnic *flexboot_nodnic, - struct flexboot_nodnic_port *port) { - mlx_status status = MLX_SUCCESS; - struct net_device *netdev; - struct ib_device *ibdev = port->ibdev; - union { - uint8_t bytes[8]; - uint32_t dwords[2]; - } mac; - - /* Allocate network devices */ - netdev = alloc_etherdev ( 0 ); - if ( netdev == NULL ) { - DBGC ( flexboot_nodnic, "flexboot_nodnic %p port %d could not allocate net device\n", - flexboot_nodnic, ibdev->port ); - status = MLX_OUT_OF_RESOURCES; - goto alloc_err; - } - port->netdev = netdev; - netdev_init ( netdev, &flexboot_nodnic_eth_operations ); - netdev->dev = ibdev->dev; - netdev->priv = port; - - status = nodnic_port_query(&port->port_priv, - nodnic_port_option_mac_high, - &mac.dwords[0]); - MLX_FATAL_CHECK_STATUS(status, mac_err, - "failed to query mac high"); - status = nodnic_port_query(&port->port_priv, - nodnic_port_option_mac_low, - &mac.dwords[1]); - MLX_FATAL_CHECK_STATUS(status, mac_err, - "failed to query mac low"); - mac.dwords[0] = htonl(mac.dwords[0]); - mac.dwords[1] = htonl(mac.dwords[1]); - memcpy ( netdev->hw_addr, - &mac.bytes[2], ETH_ALEN); - /* Register network device */ - status = register_netdev ( netdev ); - if ( status != MLX_SUCCESS ) { - DBGC ( flexboot_nodnic, - "flexboot_nodnic %p port %d could not register network device: %s\n", - flexboot_nodnic, ibdev->port, strerror ( status ) ); - goto reg_err; - } - return status; -reg_err: -mac_err: - netdev_put ( netdev ); -alloc_err: - return status; -} - -/** - * Handle flexboot_nodnic Ethernet device port state change - */ -static void flexboot_nodnic_state_change_netdev ( struct flexboot_nodnic *flexboot_nodnic __unused, - struct flexboot_nodnic_port *port, - int link_up ) { - struct net_device *netdev = port->netdev; - - if ( link_up ) - netdev_link_up ( netdev ); - else - netdev_link_down ( netdev ); - -} - -/** - * Unregister flexboot_nodnic Ethernet device - */ -static void flexboot_nodnic_unregister_netdev ( struct flexboot_nodnic *flexboot_nodnic __unused, - struct flexboot_nodnic_port *port ) { - struct net_device *netdev = port->netdev; - unregister_netdev ( netdev ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} - -/** flexboot_nodnic Ethernet port type */ -static struct flexboot_nodnic_port_type flexboot_nodnic_port_type_eth = { - .register_dev = flexboot_nodnic_register_netdev, - .state_change = flexboot_nodnic_state_change_netdev, - .unregister_dev = flexboot_nodnic_unregister_netdev, -}; - -/*************************************************************************** - * - * PCI interface helper functions - * - *************************************************************************** - */ -static -mlx_status -flexboot_nodnic_allocate_infiniband_devices( struct flexboot_nodnic *flexboot_nodnic_priv ) { - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv; - struct pci_device *pci = flexboot_nodnic_priv->pci; - struct ib_device *ibdev = NULL; - unsigned int i = 0; - - /* Allocate Infiniband devices */ - for (; i < device_priv->device_cap.num_ports; i++) { - if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) ) - continue; - ibdev = alloc_ibdev(0); - if (ibdev == NULL) { - status = MLX_OUT_OF_RESOURCES; - goto err_alloc_ibdev; - } - flexboot_nodnic_priv->port[i].ibdev = ibdev; - ibdev->op = &flexboot_nodnic_ib_operations; - ibdev->dev = &pci->dev; - ibdev->port = ( FLEXBOOT_NODNIC_PORT_BASE + i); - ib_set_drvdata(ibdev, flexboot_nodnic_priv); - } - return status; -err_alloc_ibdev: - for ( i-- ; ( signed int ) i >= 0 ; i-- ) - ibdev_put ( flexboot_nodnic_priv->port[i].ibdev ); - return status; -} - -static -mlx_status -flexboot_nodnic_thin_init_ports( struct flexboot_nodnic *flexboot_nodnic_priv ) { - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv; - nodnic_port_priv *port_priv = NULL; - unsigned int i = 0; - - for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) { - if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) ) - continue; - port_priv = &flexboot_nodnic_priv->port[i].port_priv; - status = nodnic_port_thin_init( device_priv, port_priv, i ); - MLX_FATAL_CHECK_STATUS(status, thin_init_err, - "flexboot_nodnic_thin_init_ports failed"); - } -thin_init_err: - return status; -} - - -static -mlx_status -flexboot_nodnic_set_ports_type ( struct flexboot_nodnic *flexboot_nodnic_priv ) { - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv; - nodnic_port_priv *port_priv = NULL; - nodnic_port_type type = NODNIC_PORT_TYPE_UNKNOWN; - unsigned int i = 0; - - for ( i = 0 ; i < device_priv->device_cap.num_ports ; i++ ) { - if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) ) - continue; - port_priv = &flexboot_nodnic_priv->port[i].port_priv; - status = nodnic_port_get_type(port_priv, &type); - MLX_FATAL_CHECK_STATUS(status, type_err, - "nodnic_port_get_type failed"); - switch ( type ) { - case NODNIC_PORT_TYPE_ETH: - DBGC ( flexboot_nodnic_priv, "Port %d type is Ethernet\n", i ); - flexboot_nodnic_priv->port[i].type = &flexboot_nodnic_port_type_eth; - break; - case NODNIC_PORT_TYPE_IB: - DBGC ( flexboot_nodnic_priv, "Port %d type is Infiniband\n", i ); - status = MLX_UNSUPPORTED; - goto type_err; - default: - DBGC ( flexboot_nodnic_priv, "Port %d type is unknown\n", i ); - status = MLX_UNSUPPORTED; - goto type_err; - } - } -type_err: - return status; -} - -static -mlx_status -flexboot_nodnic_ports_register_dev( struct flexboot_nodnic *flexboot_nodnic_priv ) { - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv; - struct flexboot_nodnic_port *port = NULL; - unsigned int i = 0; - - for (; i < device_priv->device_cap.num_ports; i++) { - if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) ) - continue; - port = &flexboot_nodnic_priv->port[i]; - status = port->type->register_dev ( flexboot_nodnic_priv, port ); - MLX_FATAL_CHECK_STATUS(status, reg_err, - "port register_dev failed"); - } -reg_err: - return status; -} - -static -mlx_status -flexboot_nodnic_ports_unregister_dev ( struct flexboot_nodnic *flexboot_nodnic_priv ) { - struct flexboot_nodnic_port *port; - nodnic_device_priv *device_priv = &flexboot_nodnic_priv->device_priv; - int i = (device_priv->device_cap.num_ports - 1); - - for (; i >= 0; i--) { - if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) ) - continue; - port = &flexboot_nodnic_priv->port[i]; - port->type->unregister_dev(flexboot_nodnic_priv, port); - ibdev_put(flexboot_nodnic_priv->port[i].ibdev); - } - return MLX_SUCCESS; -} - -/*************************************************************************** - * - * flexboot nodnic interface - * - *************************************************************************** - */ -__unused static void flexboot_nodnic_enable_dma ( struct flexboot_nodnic *nodnic ) { - nodnic_port_priv *port_priv; - mlx_status status; - int i; - - for ( i = 0; i < nodnic->device_priv.device_cap.num_ports; i++ ) { - if ( ! ( nodnic->port_mask & ( i + 1 ) ) ) - continue; - port_priv = & ( nodnic->port[i].port_priv ); - if ( ! ( port_priv->port_state & NODNIC_PORT_OPENED ) ) - continue; - - if ( ( status = nodnic_port_enable_dma ( port_priv ) ) ) { - MLX_DEBUG_WARN ( nodnic, "Failed to enable DMA %d\n", status ); - } - } -} - -__unused static void flexboot_nodnic_disable_dma ( struct flexboot_nodnic *nodnic ) { - int i; - - for ( i = 0; i < nodnic->device_priv.device_cap.num_ports; i++ ) { - if ( ! ( nodnic->port_mask & ( i + 1 ) ) ) - continue; - flexboot_nodnic_port_disable_dma ( & ( nodnic->port[i] ) ); - } -} - -int flexboot_nodnic_is_supported ( struct pci_device *pci ) { - mlx_utils utils; - mlx_pci_gw_buffer buffer; - mlx_status status; - int is_supported = 0; - - DBG ( "%s: start\n", __FUNCTION__ ); - - memset ( &utils, 0, sizeof ( utils ) ); - - status = mlx_utils_init ( &utils, pci ); - MLX_CHECK_STATUS ( pci, status, utils_init_err, "mlx_utils_init failed" ); - - status = mlx_pci_gw_init ( &utils ); - MLX_CHECK_STATUS ( pci, status, pci_gw_init_err, "mlx_pci_gw_init failed" ); - - status = mlx_pci_gw_read ( &utils, PCI_GW_SPACE_NODNIC, - NODNIC_NIC_INTERFACE_SUPPORTED_OFFSET, &buffer ); - - if ( status == MLX_SUCCESS ) { - buffer >>= NODNIC_NIC_INTERFACE_SUPPORTED_BIT; - is_supported = ( buffer & 0x1 ); - } - - mlx_pci_gw_teardown( &utils ); - -pci_gw_init_err: -utils_init_err: - DBG ( "%s: NODNIC is %s supported (status = %d)\n", - __FUNCTION__, ( is_supported ? "": "not" ), status ); - return is_supported; -} - -void flexboot_nodnic_copy_mac ( uint8_t mac_addr[], uint32_t low_byte, - uint16_t high_byte ) { - union mac_addr { - struct { - uint32_t low_byte; - uint16_t high_byte; - }; - uint8_t mac_addr[ETH_ALEN]; - } mac_addr_aux; - - mac_addr_aux.high_byte = high_byte; - mac_addr_aux.low_byte = low_byte; - - mac_addr[0] = mac_addr_aux.mac_addr[5]; - mac_addr[1] = mac_addr_aux.mac_addr[4]; - mac_addr[2] = mac_addr_aux.mac_addr[3]; - mac_addr[3] = mac_addr_aux.mac_addr[2]; - mac_addr[4] = mac_addr_aux.mac_addr[1]; - mac_addr[5] = mac_addr_aux.mac_addr[0]; -} - -static mlx_status flexboot_nodnic_get_factory_mac ( - struct flexboot_nodnic *flexboot_nodnic_priv, uint8_t port __unused ) { - struct mlx_vmac_query_virt_mac virt_mac; - mlx_status status; - - memset ( & virt_mac, 0, sizeof ( virt_mac ) ); - status = mlx_vmac_query_virt_mac ( flexboot_nodnic_priv->device_priv.utils, - &virt_mac ); - if ( ! status ) { - DBGC ( flexboot_nodnic_priv, "NODNIC %p Failed to set the virtual MAC\n", - flexboot_nodnic_priv ); - } - - return status; -} - -/** - * Set port masking - * - * @v flexboot_nodnic nodnic device - * @ret rc Return status code - */ -static int flexboot_nodnic_set_port_masking ( struct flexboot_nodnic *flexboot_nodnic ) { - unsigned int i; - nodnic_device_priv *device_priv = &flexboot_nodnic->device_priv; - - flexboot_nodnic->port_mask = 0; - for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) { - flexboot_nodnic->port_mask |= (i + 1); - } - - if ( ! flexboot_nodnic->port_mask ) { - /* No port was enabled */ - DBGC ( flexboot_nodnic, "NODNIC %p No port was enabled for " - "booting\n", flexboot_nodnic ); - return -ENETUNREACH; - } - - return 0; -} - -int flexboot_nodnic_probe ( struct pci_device *pci, - struct flexboot_nodnic_callbacks *callbacks, - void *drv_priv __unused ) { - mlx_status status = MLX_SUCCESS; - struct flexboot_nodnic *flexboot_nodnic_priv = NULL; - nodnic_device_priv *device_priv = NULL; - int i = 0; - - if ( ( pci == NULL ) || ( callbacks == NULL ) ) { - DBGC ( flexboot_nodnic_priv, "%s: Bad Parameter\n", __FUNCTION__ ); - return -EINVAL; - } - - flexboot_nodnic_priv = zalloc( sizeof ( *flexboot_nodnic_priv ) ); - if ( flexboot_nodnic_priv == NULL ) { - DBGC ( flexboot_nodnic_priv, "%s: Failed to allocate priv data\n", __FUNCTION__ ); - status = MLX_OUT_OF_RESOURCES; - goto device_err_alloc; - } - - /* Register settings - * Note that pci->priv will be the device private data */ - flexboot_nodnic_priv->pci = pci; - flexboot_nodnic_priv->callbacks = callbacks; - pci_set_drvdata ( pci, flexboot_nodnic_priv ); - - device_priv = &flexboot_nodnic_priv->device_priv; - device_priv->utils = (mlx_utils *)zalloc( sizeof ( mlx_utils ) ); - if ( device_priv->utils == NULL ) { - DBGC ( flexboot_nodnic_priv, "%s: Failed to allocate utils\n", __FUNCTION__ ); - status = MLX_OUT_OF_RESOURCES; - goto utils_err_alloc; - } - - status = mlx_utils_init( device_priv->utils, pci ); - MLX_FATAL_CHECK_STATUS(status, utils_init_err, - "mlx_utils_init failed"); - - /* nodnic init*/ - status = mlx_pci_gw_init( device_priv->utils ); - MLX_FATAL_CHECK_STATUS(status, cmd_init_err, - "mlx_pci_gw_init failed"); - - /* init device */ - status = nodnic_device_init( device_priv ); - MLX_FATAL_CHECK_STATUS(status, device_init_err, - "nodnic_device_init failed"); - - status = nodnic_device_get_cap( device_priv ); - MLX_FATAL_CHECK_STATUS(status, get_cap_err, - "nodnic_device_get_cap failed"); - - status = flexboot_nodnic_set_port_masking ( flexboot_nodnic_priv ); - MLX_FATAL_CHECK_STATUS(status, err_set_masking, - "flexboot_nodnic_set_port_masking failed"); - - status = flexboot_nodnic_allocate_infiniband_devices( flexboot_nodnic_priv ); - MLX_FATAL_CHECK_STATUS(status, err_alloc_ibdev, - "flexboot_nodnic_allocate_infiniband_devices failed"); - - /* port init */ - status = flexboot_nodnic_thin_init_ports( flexboot_nodnic_priv ); - MLX_FATAL_CHECK_STATUS(status, err_thin_init_ports, - "flexboot_nodnic_thin_init_ports failed"); - - /* device reg */ - status = flexboot_nodnic_set_ports_type( flexboot_nodnic_priv ); - MLX_CHECK_STATUS( flexboot_nodnic_priv, status, err_set_ports_types, - "flexboot_nodnic_set_ports_type failed"); - - status = flexboot_nodnic_ports_register_dev( flexboot_nodnic_priv ); - MLX_FATAL_CHECK_STATUS(status, reg_err, - "flexboot_nodnic_ports_register_dev failed"); - - for ( i = 0; i < device_priv->device_cap.num_ports; i++ ) { - if ( ! ( flexboot_nodnic_priv->port_mask & ( i + 1 ) ) ) - continue; - flexboot_nodnic_get_factory_mac ( flexboot_nodnic_priv, i ); - } - - /* Update ETH operations with IRQ function if supported */ - DBGC ( flexboot_nodnic_priv, "%s: %s IRQ function\n", - __FUNCTION__, ( callbacks->irq ? "Valid" : "No" ) ); - flexboot_nodnic_eth_operations.irq = callbacks->irq; - return 0; - - flexboot_nodnic_ports_unregister_dev ( flexboot_nodnic_priv ); -reg_err: -err_set_ports_types: -err_thin_init_ports: -err_alloc_ibdev: -err_set_masking: -get_cap_err: - nodnic_device_teardown ( device_priv ); -device_init_err: - mlx_pci_gw_teardown ( device_priv->utils ); -cmd_init_err: -utils_init_err: - free ( device_priv->utils ); -utils_err_alloc: - free ( flexboot_nodnic_priv ); -device_err_alloc: - return status; -} - -void flexboot_nodnic_remove ( struct pci_device *pci ) -{ - struct flexboot_nodnic *flexboot_nodnic_priv = pci_get_drvdata ( pci ); - nodnic_device_priv *device_priv = & ( flexboot_nodnic_priv->device_priv ); - - flexboot_nodnic_ports_unregister_dev ( flexboot_nodnic_priv ); - nodnic_device_teardown( device_priv ); - mlx_pci_gw_teardown( device_priv->utils ); - free( device_priv->utils ); - free( flexboot_nodnic_priv ); -} diff --git a/roms/ipxe/src/drivers/infiniband/flexboot_nodnic.h b/roms/ipxe/src/drivers/infiniband/flexboot_nodnic.h deleted file mode 100644 index 80272296c..000000000 --- a/roms/ipxe/src/drivers/infiniband/flexboot_nodnic.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef SRC_DRIVERS_INFINIBAND_FLEXBOOT_NODNIC_FLEXBOOT_NODNIC_H_ -#define SRC_DRIVERS_INFINIBAND_FLEXBOOT_NODNIC_FLEXBOOT_NODNIC_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_nodnic/include/mlx_nodnic_data_structures.h" -#include "nodnic_prm.h" -#include <ipxe/io.h> -#include <ipxe/infiniband.h> -#include <ipxe/netdevice.h> - -/* - * If defined, use interrupts in NODNIC driver - */ -#define NODNIC_IRQ_ENABLED - -#define FLEXBOOT_NODNIC_MAX_PORTS 2 -#define FLEXBOOT_NODNIC_PORT_BASE 1 - -#define FLEXBOOT_NODNIC_OPCODE_SEND 0xa - -/* Port protocol */ -enum flexboot_nodnic_protocol { - FLEXBOOT_NODNIC_PROT_IB_IPV6 = 0, - FLEXBOOT_NODNIC_PROT_ETH, - FLEXBOOT_NODNIC_PROT_IB_IPV4, - FLEXBOOT_NODNIC_PROT_FCOE -}; - -/** A flexboot nodnic port */ -struct flexboot_nodnic_port { - /** Infiniband device */ - struct ib_device *ibdev; - /** Network device */ - struct net_device *netdev; - /** nodic port */ - nodnic_port_priv port_priv; - /** Port type */ - struct flexboot_nodnic_port_type *type; - /** Ethernet completion queue */ - struct ib_completion_queue *eth_cq; - /** Ethernet queue pair */ - struct ib_queue_pair *eth_qp; -}; - - -/** A flexboot nodnic queue pair */ -struct flexboot_nodnic_queue_pair { - nodnic_qp *nodnic_queue_pair; -}; - -/** A flexboot nodnic cq */ -struct flexboot_nodnic_completion_queue { - nodnic_cq *nodnic_completion_queue; -}; - -/** A flexboot_nodnic device */ -struct flexboot_nodnic { - /** PCI device */ - struct pci_device *pci; - /** nic specific data*/ - struct flexboot_nodnic_callbacks *callbacks; - /**nodnic device*/ - nodnic_device_priv device_priv; - /**flexboot_nodnic ports*/ - struct flexboot_nodnic_port port[FLEXBOOT_NODNIC_MAX_PORTS]; - /** Device open request counter */ - unsigned int open_count; - /** Port masking */ - u16 port_mask; - /** device private data */ - void *priv_data; -}; - -/** A flexboot_nodnic port type */ -struct flexboot_nodnic_port_type { - /** Register port - * - * @v flexboot_nodnic flexboot_nodnic device - * @v port flexboot_nodnic port - * @ret mlx_status Return status code - */ - mlx_status ( * register_dev ) ( - struct flexboot_nodnic *flexboot_nodnic, - struct flexboot_nodnic_port *port - ); - /** Port state changed - * - * @v flexboot_nodnic flexboot_nodnic device - * @v port flexboot_nodnic port - * @v link_up Link is up - */ - void ( * state_change ) ( - struct flexboot_nodnic *flexboot_nodnic, - struct flexboot_nodnic_port *port, - int link_up - ); - /** Unregister port - * - * @v flexboot_nodnic flexboot_nodnic device - * @v port flexboot_nodnic port - */ - void ( * unregister_dev ) ( - struct flexboot_nodnic *flexboot_nodnic, - struct flexboot_nodnic_port *port - ); -}; - -struct cqe_data{ - mlx_boolean owner; - mlx_uint32 qpn; - mlx_uint32 is_send; - mlx_uint32 is_error; - mlx_uint32 syndrome; - mlx_uint32 vendor_err_syndrome; - mlx_uint32 wqe_counter; - mlx_uint32 byte_cnt; -}; - -struct flexboot_nodnic_callbacks { - mlx_status ( * fill_completion ) ( void *cqe, struct cqe_data *cqe_data ); - mlx_status ( * cqe_set_owner ) ( void *cq, unsigned int num_cqes ); - mlx_size ( * get_cqe_size ) (); - mlx_status ( * fill_send_wqe[5] ) ( - struct ib_device *ibdev, - struct ib_queue_pair *qp, - struct ib_address_vector *av, - struct io_buffer *iobuf, - struct nodnic_send_wqbb *wqbb, - unsigned long wqe_idx - ); - void ( * irq ) ( struct net_device *netdev, int enable ); -}; - -int flexboot_nodnic_probe ( struct pci_device *pci, - struct flexboot_nodnic_callbacks *callbacks, - void *drv_priv ); -void flexboot_nodnic_remove ( struct pci_device *pci ); -void flexboot_nodnic_eth_irq ( struct net_device *netdev, int enable ); -int flexboot_nodnic_is_supported ( struct pci_device *pci ); -void flexboot_nodnic_copy_mac ( uint8_t mac_addr[], uint32_t low_byte, - uint16_t high_byte ); - -#endif /* SRC_DRIVERS_INFINIBAND_FLEXBOOT_NODNIC_FLEXBOOT_NODNIC_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/golan.c b/roms/ipxe/src/drivers/infiniband/golan.c deleted file mode 100755 index d410fdfb9..000000000 --- a/roms/ipxe/src/drivers/infiniband/golan.c +++ /dev/null @@ -1,2672 +0,0 @@ -/* - * Copyright (C) 2013-2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <errno.h> -#include <strings.h> -#include <byteswap.h> -#include <ipxe/malloc.h> -#include <ipxe/umalloc.h> -#include <ipxe/infiniband.h> -#include <ipxe/ib_smc.h> -#include <ipxe/iobuf.h> -#include <ipxe/netdevice.h> -#include <ipxe/ethernet.h> -#include <ipxe/if_ether.h> -#include <ipxe/in.h> -#include <ipxe/ipoib.h> -#include "flexboot_nodnic.h" -#include "nodnic_shomron_prm.h" -#include "golan.h" -#include "mlx_utils/include/public/mlx_bail.h" -#include "mlx_utils/mlx_lib/mlx_link_speed/mlx_link_speed.h" -#include "mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig.h" -#include "mlx_utils/include/public/mlx_pci_gw.h" -#include "mlx_nodnic/include/mlx_port.h" - -/******************************************************************************/ -/************* Very simple memory management for umalloced pages **************/ -/******* Temporary solution until full memory management is implemented *******/ -/******************************************************************************/ -#define GOLAN_PAGES 20 -struct golan_page { - struct list_head list; - userptr_t addr; -}; - -static void golan_free_pages ( struct list_head *head ) { - struct golan_page *page, *tmp; - list_for_each_entry_safe ( page, tmp, head, list ) { - list_del ( &page->list ); - ufree ( page->addr ); - free ( page ); - } -} - -static int golan_init_pages ( struct list_head *head ) { - struct golan_page *new_entry; - int rc, i; - - if ( !head ) { - rc = -EINVAL; - goto err_golan_init_pages_bad_param; - } - - INIT_LIST_HEAD ( head ); - - for ( i = 0; i < GOLAN_PAGES; i++ ) { - new_entry = zalloc ( sizeof ( *new_entry ) ); - if ( new_entry == NULL ) { - rc = -ENOMEM; - goto err_golan_init_pages_alloc_page; - } - new_entry->addr = umalloc ( GOLAN_PAGE_SIZE ); - if ( new_entry->addr == UNULL ) { - free ( new_entry ); - rc = -ENOMEM; - goto err_golan_init_pages_alloc_page; - } - list_add ( &new_entry->list, head ); - } - - return 0; - -err_golan_init_pages_alloc_page: - golan_free_pages ( head ); -err_golan_init_pages_bad_param: - return rc; -} - -static userptr_t golan_get_page ( struct list_head *head ) { - struct golan_page *page; - userptr_t addr; - - if ( list_empty ( head ) ) - return UNULL; - - page = list_first_entry ( head, struct golan_page, list ); - list_del ( &page->list ); - addr = page->addr; - free ( page ); - return addr; -} - -/******************************************************************************/ - -const char *golan_qp_state_as_string[] = { - "RESET", - "INIT", - "RTR", - "RTS", - "SQD", - "SQE", - "ERR" -}; - -static inline int golan_check_rc_and_cmd_status ( struct golan_cmd_layout *cmd, int rc ) { - struct golan_outbox_hdr *out_hdr = ( struct golan_outbox_hdr * ) ( cmd->out ); - if ( rc == -EBUSY ) { - DBG ( "HCA is busy (rc = -EBUSY)\n" ); - return rc; - } else if ( out_hdr->status ) { - DBG("%s status = 0x%x - syndrom = 0x%x\n", __FUNCTION__, - out_hdr->status, be32_to_cpu(out_hdr->syndrome)); - return out_hdr->status; - } - return 0; -} - -#define GOLAN_CHECK_RC_AND_CMD_STATUS(_lable) \ - do { \ - if ( ( rc = golan_check_rc_and_cmd_status ( cmd, rc ) ) ) \ - goto _lable; \ - } while (0) - -#define GOLAN_PRINT_RC_AND_CMD_STATUS golan_check_rc_and_cmd_status ( cmd, rc ) - - -struct mbox { - union { - struct golan_cmd_prot_block mblock; - u8 data[MAILBOX_STRIDE]; - __be64 qdata[MAILBOX_STRIDE >> 3]; - }; -}; - -static inline uint32_t ilog2(uint32_t mem) -{ - return ( fls ( mem ) - 1 ); -} - -#define CTRL_SIG_SZ (sizeof(mailbox->mblock) - sizeof(mailbox->mblock.bdata) - 2) - -static inline u8 xor8_buf(void *buf, int len) -{ - u8 sum = 0; - int i; - u8 *ptr = buf; - - for (i = 0; i < len; ++i) - sum ^= ptr[i]; - - return sum; -} - -static inline int verify_block_sig(struct golan_cmd_prot_block *block) -{ - if (xor8_buf(block->rsvd0, sizeof(*block) - sizeof(block->data) - 1) != 0xff) - return -EINVAL; - - if (xor8_buf(block, sizeof(*block)) != 0xff) - return -EINVAL; - return 0; -} - -static inline const char *cmd_status_str(u8 status) -{ - switch (status) { - case 0x0: return "OK"; - case 0x1: return "internal error"; - case 0x2: return "bad operation"; - case 0x3: return "bad parameter"; - case 0x4: return "bad system state"; - case 0x5: return "bad resource"; - case 0x6: return "resource busy"; - case 0x8: return "limits exceeded"; - case 0x9: return "bad resource state"; - case 0xa: return "bad index"; - case 0xf: return "no resources"; - case 0x50: return "bad input length"; - case 0x51: return "bad output length"; - case 0x10: return "bad QP state"; - case 0x30: return "bad packet (discarded)"; - case 0x40: return "bad size too many outstanding CQEs"; - case 0xff: return "Command Timed Out"; - default: return "unknown status"; - } -} - -static inline uint16_t fw_rev_maj(struct golan *golan) -{ - return be32_to_cpu(readl(&golan->iseg->fw_rev)) & 0xffff; -} - -static inline u16 fw_rev_min(struct golan *golan) -{ - return be32_to_cpu(readl(&golan->iseg->fw_rev)) >> 16; -} - -static inline u16 fw_rev_sub(struct golan *golan) -{ - return be32_to_cpu(readl(&golan->iseg->cmdif_rev_fw_sub)) & 0xffff; -} - -static inline u16 cmdif_rev(struct golan *golan) -{ - return be32_to_cpu(readl(&golan->iseg->cmdif_rev_fw_sub)) >> 16; -} - - -static inline struct golan_cmd_layout *get_cmd( struct golan *golan, int idx ) -{ - return golan->cmd.addr + (idx << golan->cmd.log_stride); -} - -static inline void golan_calc_sig(struct golan *golan, uint32_t cmd_idx, - uint32_t inbox_idx, uint32_t outbox_idx) -{ - struct golan_cmd_layout *cmd = get_cmd(golan, cmd_idx); - struct mbox *mailbox = NULL; - - if (inbox_idx != NO_MBOX) { - mailbox = GET_INBOX(golan, inbox_idx); - mailbox->mblock.token = cmd->token; - mailbox->mblock.ctrl_sig = ~xor8_buf(mailbox->mblock.rsvd0, - CTRL_SIG_SZ); - } - if (outbox_idx != NO_MBOX) { - mailbox = GET_OUTBOX(golan, outbox_idx); - mailbox->mblock.token = cmd->token; - mailbox->mblock.ctrl_sig = ~xor8_buf(mailbox->mblock.rsvd0, - CTRL_SIG_SZ); - } - cmd->sig = ~xor8_buf(cmd, sizeof(*cmd)); -} - -/** - * Get Golan FW - */ -static int fw_ver_and_cmdif ( struct golan *golan ) { - DBGC (golan ,"\n[%x:%x]rev maj.min.submin = %x.%x.%x cmdif = %x\n", - golan->iseg->fw_rev, - golan->iseg->cmdif_rev_fw_sub, - fw_rev_maj ( golan ), fw_rev_min ( golan ), - fw_rev_sub ( golan ), cmdif_rev ( golan)); - - if (cmdif_rev ( golan) != PXE_CMDIF_REF) { - DBGC (golan ,"CMDIF %d not supported current is %d\n", - cmdif_rev ( golan ), PXE_CMDIF_REF); - return 1; - } - return 0; -} - -static inline void show_out_status(uint32_t *out) -{ - DBG("%x\n", be32_to_cpu(out[0])); - DBG("%x\n", be32_to_cpu(out[1])); - DBG("%x\n", be32_to_cpu(out[2])); - DBG("%x\n", be32_to_cpu(out[3])); -} -/** - * Check if CMD has finished. - */ -static inline uint32_t is_command_finished( struct golan *golan, int idx) -{ - wmb(); - return !(get_cmd( golan , idx )->status_own & CMD_OWNER_HW); -} - -/** - * Wait for Golan command completion - * - * @v golan Golan device - * @ret rc Return status code - */ -static inline int golan_cmd_wait(struct golan *golan, int idx, const char *command) -{ - unsigned int wait; - int rc = -EBUSY; - - for ( wait = GOLAN_HCR_MAX_WAIT_MS ; wait ; --wait ) { - if (is_command_finished(golan, idx)) { - rc = CMD_STATUS(golan, idx); - rmb(); - break; - } else { - mdelay ( 1 ); - } - } - if (rc) { - DBGC (golan ,"[%s]RC is %s[%x]\n", command, cmd_status_str(rc), rc); - } - - golan->cmd_bm &= ~(1 << idx); - return rc; -} - -/** - * Notify the HW that commands are ready - */ -static inline void send_command(struct golan *golan) -{ - wmb(); //Make sure the command is visible in "memory". - writel(cpu_to_be32(golan->cmd_bm) , &golan->iseg->cmd_dbell); -} - -static inline int send_command_and_wait(struct golan *golan, uint32_t cmd_idx, - uint32_t inbox_idx, uint32_t outbox_idx, const char *command) -{ - golan_calc_sig(golan, cmd_idx, inbox_idx, outbox_idx); - send_command(golan); - return golan_cmd_wait(golan, cmd_idx, command); -} - -/** - * Prepare a FW command, - * In - comamnd idx (Must be valid) - * writes the command parameters. - */ -static inline struct golan_cmd_layout *write_cmd(struct golan *golan, int idx, - uint16_t opcode, uint16_t opmod, - uint16_t inbox_idx, - uint16_t outbox_idx, uint16_t inlen, - uint16_t outlen) -{ - struct golan_cmd_layout *cmd = get_cmd(golan , idx); - struct golan_inbox_hdr *hdr = (struct golan_inbox_hdr *)cmd->in; - static uint8_t token; - - memset(cmd, 0, sizeof(*cmd)); - - cmd->type = GOLAN_PCI_CMD_XPORT; - cmd->status_own = CMD_OWNER_HW; - cmd->outlen = cpu_to_be32(outlen); - cmd->inlen = cpu_to_be32(inlen); - hdr->opcode = cpu_to_be16(opcode); - hdr->opmod = cpu_to_be16(opmod); - - if (inbox_idx != NO_MBOX) { - memset(GET_INBOX(golan, inbox_idx), 0, MAILBOX_SIZE); - cmd->in_ptr = VIRT_2_BE64_BUS(GET_INBOX(golan, inbox_idx)); - cmd->token = ++token; - } - if (outbox_idx != NO_MBOX) { - memset(GET_OUTBOX(golan, outbox_idx), 0, MAILBOX_SIZE); - cmd->out_ptr = VIRT_2_BE64_BUS(GET_OUTBOX(golan, outbox_idx)); - } - - golan->cmd_bm |= 1 << idx; - - assert ( cmd != NULL ); - return cmd; -} - -static inline int golan_core_enable_hca(struct golan *golan) -{ - struct golan_cmd_layout *cmd; - int rc = 0; - - DBGC(golan, "%s\n", __FUNCTION__); - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_ENABLE_HCA, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_enable_hca_mbox_in), - sizeof(struct golan_enable_hca_mbox_out)); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - return rc; -} - -static inline void golan_disable_hca(struct golan *golan) -{ - struct golan_cmd_layout *cmd; - int rc; - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_DISABLE_HCA, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_disable_hca_mbox_in), - sizeof(struct golan_disable_hca_mbox_out)); - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; -} - -static inline int golan_set_hca_cap(struct golan *golan) -{ - struct golan_cmd_layout *cmd; - int rc; - - DBGC(golan, "%s\n", __FUNCTION__); - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_SET_HCA_CAP, 0x0, - GEN_MBOX, NO_MBOX, - sizeof(struct golan_cmd_set_hca_cap_mbox_in), - sizeof(struct golan_cmd_set_hca_cap_mbox_out)); - - golan->caps.flags &= ~GOLAN_DEV_CAP_FLAG_CMDIF_CSUM; - DBGC( golan , "%s caps.uar_sz = %d\n", __FUNCTION__, golan->caps.uar_sz); - DBGC( golan , "%s caps.log_pg_sz = %d\n", __FUNCTION__, golan->caps.log_pg_sz); - DBGC( golan , "%s caps.log_uar_sz = %d\n", __FUNCTION__, be32_to_cpu(golan->caps.uar_page_sz)); - golan->caps.uar_page_sz = 0; - - - memcpy(((struct golan_hca_cap *)GET_INBOX(golan, GEN_MBOX)), - &(golan->caps), - sizeof(struct golan_hca_cap)); - - //if command failed we should reset the caps in golan->caps - rc = send_command_and_wait(golan, DEF_CMD_IDX, GEN_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - return rc; -} - -static inline int golan_qry_hca_cap(struct golan *golan) -{ - struct golan_cmd_layout *cmd; - int rc = 0; - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_QUERY_HCA_CAP, 0x1, - NO_MBOX, GEN_MBOX, - sizeof(struct golan_cmd_query_hca_cap_mbox_in), - sizeof(struct golan_cmd_query_hca_cap_mbox_out)); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, GEN_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_query_hca_cap ); - - memcpy(&(golan->caps), - ((struct golan_hca_cap *)GET_OUTBOX(golan, GEN_MBOX)), - sizeof(struct golan_hca_cap)); -err_query_hca_cap: - return rc; -} - -static inline int golan_take_pages ( struct golan *golan, uint32_t pages, __be16 func_id ) { - uint32_t out_num_entries = 0; - int size_ibox = sizeof(struct golan_manage_pages_inbox); - int size_obox = sizeof(struct golan_manage_pages_outbox); - int rc = 0; - - DBGC(golan, "%s\n", __FUNCTION__); - - while ( pages > 0 ) { - uint32_t pas_num = min(pages, MAX_PASE_MBOX); - unsigned i; - struct golan_cmd_layout *cmd; - struct golan_manage_pages_inbox *in; - struct golan_manage_pages_outbox_data *out; - - size_ibox += (pas_num * GOLAN_PAS_SIZE); - size_obox += (pas_num * GOLAN_PAS_SIZE); - - cmd = write_cmd(golan, MEM_CMD_IDX, GOLAN_CMD_OP_MANAGE_PAGES, GOLAN_PAGES_TAKE, - MEM_MBOX, MEM_MBOX, - size_ibox, - size_obox); - - in = (struct golan_manage_pages_inbox *)cmd->in; /* Warning (WE CANT USE THE LAST 2 FIELDS) */ - - in->func_id = func_id; /* Already BE */ - in->num_entries = cpu_to_be32(pas_num); - - if ( ( rc = send_command_and_wait(golan, MEM_CMD_IDX, MEM_MBOX, MEM_MBOX, __FUNCTION__) ) == 0 ) { - out = (struct golan_manage_pages_outbox_data *)GET_OUTBOX(golan, MEM_MBOX); - out_num_entries = be32_to_cpu(((struct golan_manage_pages_outbox *)(cmd->out))->num_entries); - for (i = 0; i < out_num_entries; ++i) { - ufree(BE64_BUS_2_USR(out->pas[i])); - } - } else { - if ( rc == -EBUSY ) { - DBGC (golan ,"HCA is busy (rc = -EBUSY)\n" ); - } else { - DBGC (golan ,"%s: rc =0x%x[%s]<%x> syn 0x%x[0x%x] for %d pages\n", - __FUNCTION__, rc, cmd_status_str(rc), - CMD_SYND(golan, MEM_CMD_IDX), - get_cmd( golan , MEM_CMD_IDX )->status_own, - be32_to_cpu(CMD_SYND(golan, MEM_CMD_IDX)), pas_num); - } - return rc; - } - - pages -= out_num_entries; - } - DBGC( golan , "%s Pages handled\n", __FUNCTION__); - return 0; -} - -static inline int golan_provide_pages ( struct golan *golan , uint32_t pages, __be16 func_id ) { - struct mbox *mailbox; - int size_ibox = sizeof(struct golan_manage_pages_inbox); - int size_obox = sizeof(struct golan_manage_pages_outbox); - int rc = 0; - - DBGC(golan, "%s\n", __FUNCTION__); - - while ( pages > 0 ) { - uint32_t pas_num = min(pages, MAX_PASE_MBOX); - unsigned i, j; - struct golan_cmd_layout *cmd; - struct golan_manage_pages_inbox *in; - userptr_t addr = 0; - - mailbox = GET_INBOX(golan, MEM_MBOX); - size_ibox += (pas_num * GOLAN_PAS_SIZE); - size_obox += (pas_num * GOLAN_PAS_SIZE); - - cmd = write_cmd(golan, MEM_CMD_IDX, GOLAN_CMD_OP_MANAGE_PAGES, GOLAN_PAGES_GIVE, - MEM_MBOX, MEM_MBOX, - size_ibox, - size_obox); - - in = (struct golan_manage_pages_inbox *)cmd->in; /* Warning (WE CANT USE THE LAST 2 FIELDS) */ - - in->func_id = func_id; /* Already BE */ - in->num_entries = cpu_to_be32(pas_num); - - for ( i = 0 , j = MANAGE_PAGES_PSA_OFFSET; i < pas_num; ++i ,++j ) { - if (!(addr = umalloc(GOLAN_PAGE_SIZE))) { - rc = -ENOMEM; - DBGC (golan ,"Couldnt allocated page \n"); - goto malloc_dma_failed; - } - if (GOLAN_PAGE_MASK & user_to_phys(addr, 0)) { - DBGC (golan ,"Addr not Page alligned [%lx %lx]\n", user_to_phys(addr, 0), addr); - } - mailbox->mblock.data[j] = USR_2_BE64_BUS(addr); - } - - if ( ( rc = send_command_and_wait(golan, MEM_CMD_IDX, MEM_MBOX, MEM_MBOX, __FUNCTION__) ) == 0 ) { - pages -= pas_num; - golan->total_dma_pages += pas_num; - } else { - if ( rc == -EBUSY ) { - DBGC (golan ,"HCA is busy (rc = -EBUSY)\n" ); - } else { - DBGC (golan ,"%s: rc =0x%x[%s]<%x> syn 0x%x[0x%x] for %d pages\n", - __FUNCTION__, rc, cmd_status_str(rc), - CMD_SYND(golan, MEM_CMD_IDX), - get_cmd( golan , MEM_CMD_IDX )->status_own, - be32_to_cpu(CMD_SYND(golan, MEM_CMD_IDX)), pas_num); - } - ufree ( addr ); - goto err_send_command; - } - } - DBGC( golan , "%s Pages handled\n", __FUNCTION__); - return 0; - -err_send_command: -malloc_dma_failed: - /* Go over In box and free pages */ - /* Send Error to FW */ - /* What is next - Disable HCA? */ - DBGC (golan ,"%s Failed (rc = 0x%x)\n", __FUNCTION__, rc); - return rc; -} - -static inline int golan_handle_pages(struct golan *golan, - enum golan_qry_pages_mode qry, - enum golan_manage_pages_mode mode) -{ - struct golan_cmd_layout *cmd; - - int rc = 0; - int32_t pages; - uint16_t total_pages; - __be16 func_id; - - DBGC(golan, "%s\n", __FUNCTION__); - - cmd = write_cmd(golan, MEM_CMD_IDX, GOLAN_CMD_OP_QUERY_PAGES, qry, - NO_MBOX, NO_MBOX, - sizeof(struct golan_query_pages_inbox), - sizeof(struct golan_query_pages_outbox)); - - rc = send_command_and_wait(golan, MEM_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_handle_pages_query ); - - pages = be32_to_cpu(QRY_PAGES_OUT(golan, MEM_CMD_IDX)->num_pages); - - DBGC( golan , "%s pages needed: %d\n", __FUNCTION__, pages); - - func_id = QRY_PAGES_OUT(golan, MEM_CMD_IDX)->func_id; - - total_pages = (( pages >= 0 ) ? pages : ( pages * ( -1 ) )); - - if ( mode == GOLAN_PAGES_GIVE ) { - rc = golan_provide_pages(golan, total_pages, func_id); - } else { - rc = golan_take_pages(golan, golan->total_dma_pages, func_id); - golan->total_dma_pages = 0; - } - - if ( rc ) { - DBGC (golan , "Failed to %s pages (rc = %d) - DMA pages allocated = %d\n", - ( ( mode == GOLAN_PAGES_GIVE ) ? "give" : "take" ), rc , golan->total_dma_pages ); - return rc; - } - - return 0; - -err_handle_pages_query: - DBGC (golan ,"%s Qyery pages failed (rc = 0x%x)\n", __FUNCTION__, rc); - return rc; -} - -static inline int golan_set_access_reg ( struct golan *golan __attribute__ (( unused )), uint32_t reg __attribute__ (( unused ))) -{ -#if 0 - write_cmd(golan, _CMD_IDX, GOLAN_CMD_OP_QUERY_PAGES, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_reg_host_endianess), - sizeof(struct golan_reg_host_endianess)); - in->arg = cpu_to_be32(arg); - in->register_id = cpu_to_be16(reg_num); -#endif - DBGC (golan ," %s Not implemented yet\n", __FUNCTION__); - return 0; -} - -static inline void golan_cmd_uninit ( struct golan *golan ) -{ - free_dma(golan->mboxes.outbox, GOLAN_PAGE_SIZE); - free_dma(golan->mboxes.inbox, GOLAN_PAGE_SIZE); - free_dma(golan->cmd.addr, GOLAN_PAGE_SIZE); -} - -/** - * Initialise Golan Command Q parameters - * -- Alocate a 4kb page for the Command Q - * -- Read the stride and log num commands available - * -- Write the address to cmdq_phy_addr in iseg - * @v golan Golan device - */ -static inline int golan_cmd_init ( struct golan *golan ) -{ - int rc = 0; - uint32_t addr_l_sz; - - if (!(golan->cmd.addr = malloc_dma(GOLAN_PAGE_SIZE , GOLAN_PAGE_SIZE))) { - rc = -ENOMEM; - goto malloc_dma_failed; - } - if (!(golan->mboxes.inbox = malloc_dma(GOLAN_PAGE_SIZE , GOLAN_PAGE_SIZE))) { - rc = -ENOMEM; - goto malloc_dma_inbox_failed; - } - if (!(golan->mboxes.outbox = malloc_dma(GOLAN_PAGE_SIZE , GOLAN_PAGE_SIZE))) { - rc = -ENOMEM; - goto malloc_dma_outbox_failed; - } - addr_l_sz = be32_to_cpu(readl(&golan->iseg->cmdq_addr_l_sz)); - - golan->cmd.log_stride = addr_l_sz & 0xf; - golan->cmd.size = 1 << (( addr_l_sz >> 4 ) & 0xf); - - addr_l_sz = virt_to_bus(golan->cmd.addr); - writel(0 /* cpu_to_be32(golan->cmd.addr) >> 32 */, &golan->iseg->cmdq_addr_h); - writel(cpu_to_be32(addr_l_sz), &golan->iseg->cmdq_addr_l_sz); - wmb(); //Make sure the addr is visible in "memory". - - addr_l_sz = be32_to_cpu(readl(&golan->iseg->cmdq_addr_l_sz)); - - DBGC( golan , "%s Command interface was initialized\n", __FUNCTION__); - return 0; - -malloc_dma_outbox_failed: - free_dma(golan->mboxes.inbox, GOLAN_PAGE_SIZE); -malloc_dma_inbox_failed: - free_dma(golan->cmd.addr, GOLAN_PAGE_SIZE); -malloc_dma_failed: - DBGC (golan ,"%s Failed to initialize command interface (rc = 0x%x)\n", - __FUNCTION__, rc); - return rc; -} - -static inline int golan_hca_init(struct golan *golan) -{ - struct golan_cmd_layout *cmd; - int rc = 0; - - DBGC(golan, "%s\n", __FUNCTION__); - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_INIT_HCA, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_cmd_init_hca_mbox_in), - sizeof(struct golan_cmd_init_hca_mbox_out)); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - return rc; -} - -static inline void golan_teardown_hca(struct golan *golan, enum golan_teardown op_mod) -{ - struct golan_cmd_layout *cmd; - int rc; - - DBGC (golan, "%s in\n", __FUNCTION__); - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_TEARDOWN_HCA, op_mod, - NO_MBOX, NO_MBOX, - sizeof(struct golan_cmd_teardown_hca_mbox_in), - sizeof(struct golan_cmd_teardown_hca_mbox_out)); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - - DBGC (golan, "%s HCA teardown compleated\n", __FUNCTION__); -} - -static inline int golan_alloc_uar(struct golan *golan) -{ - struct golan_uar *uar = &golan->uar; - struct golan_cmd_layout *cmd; - struct golan_alloc_uar_mbox_out *out; - int rc; - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_ALLOC_UAR, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_alloc_uar_mbox_in), - sizeof(struct golan_alloc_uar_mbox_out)); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_alloc_uar_cmd ); - out = (struct golan_alloc_uar_mbox_out *) ( cmd->out ); - - uar->index = be32_to_cpu(out->uarn) & 0xffffff; - - uar->phys = (pci_bar_start(golan->pci, GOLAN_HCA_BAR) + (uar->index << GOLAN_PAGE_SHIFT)); - uar->virt = (void *)(ioremap(uar->phys, GOLAN_PAGE_SIZE)); - - DBGC( golan , "%s: UAR allocated with index 0x%x\n", __FUNCTION__, uar->index); - return 0; - -err_alloc_uar_cmd: - DBGC (golan ,"%s [%d] out\n", __FUNCTION__, rc); - return rc; -} - -static void golan_dealloc_uar(struct golan *golan) -{ - struct golan_cmd_layout *cmd; - uint32_t uar_index = golan->uar.index; - int rc; - - DBGC (golan, "%s in\n", __FUNCTION__); - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_DEALLOC_UAR, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_free_uar_mbox_in), - sizeof(struct golan_free_uar_mbox_out)); - - ((struct golan_free_uar_mbox_in *)(cmd->in))->uarn = cpu_to_be32(uar_index); - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - golan->uar.index = 0; - - DBGC (golan, "%s UAR (0x%x) was destroyed\n", __FUNCTION__, uar_index); -} - -static void golan_eq_update_ci(struct golan_event_queue *eq, int arm) -{ - __be32 *addr = eq->doorbell + (arm ? 0 : 2); - u32 val = (eq->cons_index & 0xffffff) | (eq->eqn << 24); - writel(cpu_to_be32(val) , addr); - /* We still want ordering, just not swabbing, so add a barrier */ - wmb(); -} - -static int golan_create_eq(struct golan *golan) -{ - struct golan_event_queue *eq = &golan->eq; - struct golan_create_eq_mbox_in_data *in; - struct golan_cmd_layout *cmd; - struct golan_create_eq_mbox_out *out; - int rc, i; - userptr_t addr; - - eq->cons_index = 0; - eq->size = GOLAN_NUM_EQES * sizeof(eq->eqes[0]); - addr = golan_get_page ( &golan->pages ); - if (!addr) { - rc = -ENOMEM; - goto err_create_eq_eqe_alloc; - } - eq->eqes = (struct golan_eqe *)user_to_virt(addr, 0); - - /* Set EQEs ownership bit to HW ownership */ - for (i = 0; i < GOLAN_NUM_EQES; ++i) { - eq->eqes[i].owner = GOLAN_EQE_HW_OWNERSHIP; - } - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_CREATE_EQ, 0x0, - GEN_MBOX, NO_MBOX, - sizeof(struct golan_create_eq_mbox_in) + GOLAN_PAS_SIZE, - sizeof(struct golan_create_eq_mbox_out)); - - in = (struct golan_create_eq_mbox_in_data *)GET_INBOX(golan, GEN_MBOX); - - /* Fill the physical address of the page */ - in->pas[0] = USR_2_BE64_BUS(addr); - in->ctx.log_sz_usr_page = cpu_to_be32((ilog2(GOLAN_NUM_EQES)) << 24 | golan->uar.index); - DBGC( golan , "UAR idx %x (BE %x)\n", golan->uar.index, in->ctx.log_sz_usr_page); - in->events_mask = cpu_to_be64(1 << GOLAN_EVENT_TYPE_PORT_CHANGE); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, GEN_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_create_eq_cmd ); - out = (struct golan_create_eq_mbox_out *)cmd->out; - - eq->eqn = out->eq_number; - eq->doorbell = ((void *)golan->uar.virt) + GOLAN_EQ_DOORBELL_OFFSET; - - /* EQs are created in ARMED state */ - golan_eq_update_ci(eq, GOLAN_EQ_UNARMED); - - DBGC( golan , "%s: Event queue created (EQN = 0x%x)\n", __FUNCTION__, eq->eqn); - return 0; - -err_create_eq_cmd: - ufree(virt_to_user(golan->eq.eqes)); -err_create_eq_eqe_alloc: - DBGC (golan ,"%s [%d] out\n", __FUNCTION__, rc); - return rc; -} - -static void golan_destory_eq(struct golan *golan) -{ - struct golan_cmd_layout *cmd; - struct golan_destroy_eq_mbox_in *in; - uint8_t eqn = golan->eq.eqn; - int rc; - - DBGC (golan, "%s in\n", __FUNCTION__); - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_DESTROY_EQ, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_destroy_eq_mbox_in), - sizeof(struct golan_destroy_eq_mbox_out)); - - in = GOLAN_MBOX_IN ( cmd, in ); - in->eqn = eqn; - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - - ufree(virt_to_user(golan->eq.eqes)); - golan->eq.eqn = 0; - - DBGC( golan, "%s Event queue (0x%x) was destroyed\n", __FUNCTION__, eqn); -} - -static int golan_alloc_pd(struct golan *golan) -{ - struct golan_cmd_layout *cmd; - struct golan_alloc_pd_mbox_out *out; - int rc; - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_ALLOC_PD, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_alloc_pd_mbox_in), - sizeof(struct golan_alloc_pd_mbox_out)); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_alloc_pd_cmd ); - out = (struct golan_alloc_pd_mbox_out *) ( cmd->out ); - - golan->pdn = (be32_to_cpu(out->pdn) & 0xffffff); - DBGC( golan , "%s: Protection domain created (PDN = 0x%x)\n", __FUNCTION__, - golan->pdn); - return 0; - -err_alloc_pd_cmd: - DBGC (golan ,"%s [%d] out\n", __FUNCTION__, rc); - return rc; -} - -static void golan_dealloc_pd(struct golan *golan) -{ - struct golan_cmd_layout *cmd; - uint32_t pdn = golan->pdn; - int rc; - - DBGC (golan,"%s in\n", __FUNCTION__); - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_DEALLOC_PD, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_alloc_pd_mbox_in), - sizeof(struct golan_alloc_pd_mbox_out)); - - ((struct golan_dealloc_pd_mbox_in *)(cmd->in))->pdn = cpu_to_be32(pdn); - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - golan->pdn = 0; - - DBGC (golan ,"%s Protection domain (0x%x) was destroyed\n", __FUNCTION__, pdn); -} - -static int golan_create_mkey(struct golan *golan) -{ - struct golan_create_mkey_mbox_in_data *in; - struct golan_cmd_layout *cmd; - struct golan_create_mkey_mbox_out *out; - int rc; - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_CREATE_MKEY, 0x0, - GEN_MBOX, NO_MBOX, - sizeof(struct golan_create_mkey_mbox_in), - sizeof(struct golan_create_mkey_mbox_out)); - - in = (struct golan_create_mkey_mbox_in_data *)GET_INBOX(golan, GEN_MBOX); - - in->seg.flags = GOLAN_IB_ACCESS_LOCAL_WRITE | GOLAN_IB_ACCESS_LOCAL_READ; - in->seg.flags_pd = cpu_to_be32(golan->pdn | GOLAN_MKEY_LEN64); - in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << GOLAN_CREATE_MKEY_SEG_QPN_BIT); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, GEN_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_create_mkey_cmd ); - out = (struct golan_create_mkey_mbox_out *) ( cmd->out ); - - golan->mkey = ((be32_to_cpu(out->mkey) & 0xffffff) << 8); - DBGC( golan , "%s: Got DMA Key for local access read/write (MKEY = 0x%x)\n", - __FUNCTION__, golan->mkey); - return 0; -err_create_mkey_cmd: - DBGC (golan ,"%s [%d] out\n", __FUNCTION__, rc); - return rc; -} - -static void golan_destroy_mkey(struct golan *golan) -{ - struct golan_cmd_layout *cmd; - u32 mkey = golan->mkey; - int rc; - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_DESTROY_MKEY, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_destroy_mkey_mbox_in), - sizeof(struct golan_destroy_mkey_mbox_out)); - ((struct golan_destroy_mkey_mbox_in *)(cmd->in))->mkey = cpu_to_be32(mkey >> 8); - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - golan->mkey = 0; - - DBGC( golan , "%s DMA Key (0x%x) for local access write was destroyed\n" - , __FUNCTION__, mkey); -} - - -/** - * Initialise Golan PCI parameters - * - * @v golan Golan device - */ -static inline void golan_pci_init(struct golan *golan) -{ - struct pci_device *pci = golan->pci; - - /* Fix up PCI device */ - adjust_pci_device ( pci ); - - /* Get HCA BAR */ - golan->iseg = ioremap ( pci_bar_start ( pci, GOLAN_HCA_BAR), - GOLAN_PCI_CONFIG_BAR_SIZE ); -} - -static inline struct golan *golan_alloc() -{ - void *golan = zalloc(sizeof(struct golan)); - if ( !golan ) - goto err_zalloc; - - return golan; - -err_zalloc: - return NULL; -} - -/** - * Create completion queue - * - * @v ibdev Infiniband device - * @v cq Completion queue - * @ret rc Return status code - */ -static int golan_create_cq(struct ib_device *ibdev, - struct ib_completion_queue *cq) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_completion_queue *golan_cq; - struct golan_cmd_layout *cmd; - struct golan_create_cq_mbox_in_data *in; - struct golan_create_cq_mbox_out *out; - int rc; - unsigned int i; - userptr_t addr; - - golan_cq = zalloc(sizeof(*golan_cq)); - if (!golan_cq) { - rc = -ENOMEM; - goto err_create_cq; - } - golan_cq->size = sizeof(golan_cq->cqes[0]) * cq->num_cqes; - golan_cq->doorbell_record = malloc_dma(GOLAN_CQ_DB_RECORD_SIZE, - GOLAN_CQ_DB_RECORD_SIZE); - if (!golan_cq->doorbell_record) { - rc = -ENOMEM; - goto err_create_cq_db_alloc; - } - - addr = golan_get_page ( &golan->pages ); - if (!addr) { - rc = -ENOMEM; - goto err_create_cq_cqe_alloc; - } - golan_cq->cqes = (struct golan_cqe64 *)user_to_virt(addr, 0); - - /* Set CQEs ownership bit to HW ownership */ - for (i = 0; i < cq->num_cqes; ++i) { - golan_cq->cqes[i].op_own = ((GOLAN_CQE_OPCODE_NOT_VALID << - GOLAN_CQE_OPCODE_BIT) | - GOLAN_CQE_HW_OWNERSHIP); - } - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_CREATE_CQ, 0x0, - GEN_MBOX, NO_MBOX, - sizeof(struct golan_create_cq_mbox_in) + GOLAN_PAS_SIZE, - sizeof(struct golan_create_cq_mbox_out)); - - in = (struct golan_create_cq_mbox_in_data *)GET_INBOX(golan, GEN_MBOX); - - /* Fill the physical address of the page */ - in->pas[0] = USR_2_BE64_BUS(addr); - in->ctx.cqe_sz_flags = GOLAN_CQE_SIZE_64 << 5; - in->ctx.log_sz_usr_page = cpu_to_be32(((ilog2(cq->num_cqes)) << 24) | golan->uar.index); - in->ctx.c_eqn = cpu_to_be16(golan->eq.eqn); - in->ctx.db_record_addr = VIRT_2_BE64_BUS(golan_cq->doorbell_record); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, GEN_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_create_cq_cmd ); - out = (struct golan_create_cq_mbox_out *) ( cmd->out ); - - cq->cqn = (be32_to_cpu(out->cqn) & 0xffffff); - - ib_cq_set_drvdata(cq, golan_cq); - - DBGC( golan , "%s CQ created successfully (CQN = 0x%lx)\n", __FUNCTION__, cq->cqn); - return 0; - -err_create_cq_cmd: - ufree(virt_to_user(golan_cq->cqes)); -err_create_cq_cqe_alloc: - free_dma(golan_cq->doorbell_record, GOLAN_CQ_DB_RECORD_SIZE); -err_create_cq_db_alloc: - free ( golan_cq ); -err_create_cq: - DBGC (golan ,"%s out rc = 0x%x\n", __FUNCTION__, rc); - return rc; -} - -/** - * Destroy completion queue - * - * @v ibdev Infiniband device - * @v cq Completion queue - */ -static void golan_destroy_cq(struct ib_device *ibdev, - struct ib_completion_queue *cq) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_completion_queue *golan_cq = ib_cq_get_drvdata(cq); - struct golan_cmd_layout *cmd; - uint32_t cqn = cq->cqn; - int rc; - - DBGC (golan, "%s in\n", __FUNCTION__); - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_DESTROY_CQ, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_destroy_cq_mbox_in), - sizeof(struct golan_destroy_cq_mbox_out)); - ((struct golan_destroy_cq_mbox_in *)(cmd->in))->cqn = cpu_to_be32(cqn); - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - cq->cqn = 0; - - ib_cq_set_drvdata(cq, NULL); - ufree(virt_to_user(golan_cq->cqes)); - free_dma(golan_cq->doorbell_record, GOLAN_CQ_DB_RECORD_SIZE); - free(golan_cq); - - DBGC (golan, "%s CQ number 0x%x was destroyed\n", __FUNCTION__, cqn); -} - -static void golan_cq_clean(struct ib_completion_queue *cq) -{ - ib_poll_cq(cq->ibdev, cq); -} - -static int golan_qp_type_to_st(enum ib_queue_pair_type type) -{ - int qpt = type; - - switch (qpt) { - case IB_QPT_RC: - return GOLAN_QP_ST_RC; - case IB_QPT_UD: - return GOLAN_QP_ST_UD; - case IB_QPT_SMI: - return GOLAN_QP_ST_QP0; - case IB_QPT_GSI: - return GOLAN_QP_ST_QP1; - case IB_QPT_ETH: - default: - return -EINVAL; - } -} -#if 0 -static int golan_is_special_qp(enum ib_queue_pair_type type) -{ - return (type == IB_QPT_GSI || type == IB_QPT_SMI); -} -#endif -static int golan_create_qp_aux(struct ib_device *ibdev, - struct ib_queue_pair *qp, - int *qpn) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_queue_pair *golan_qp; - struct golan_create_qp_mbox_in_data *in; - struct golan_cmd_layout *cmd; - struct golan_wqe_data_seg *data; - struct golan_create_qp_mbox_out *out; - userptr_t addr; - uint32_t wqe_size_in_bytes; - uint32_t max_qp_size_in_wqes; - unsigned int i; - int rc; - - golan_qp = zalloc(sizeof(*golan_qp)); - if (!golan_qp) { - rc = -ENOMEM; - goto err_create_qp; - } - - if ( ( qp->type == IB_QPT_SMI ) || ( qp->type == IB_QPT_GSI ) || - ( qp->type == IB_QPT_UD ) ) { - golan_qp->rq.grh_size = ( qp->recv.num_wqes * - sizeof ( golan_qp->rq.grh[0] )); - } - - /* Calculate receive queue size */ - golan_qp->rq.size = qp->recv.num_wqes * GOLAN_RECV_WQE_SIZE; - if (GOLAN_RECV_WQE_SIZE > be16_to_cpu(golan->caps.max_wqe_sz_rq)) { - DBGC (golan ,"%s receive wqe size [%zd] > max wqe size [%d]\n", __FUNCTION__, - GOLAN_RECV_WQE_SIZE, be16_to_cpu(golan->caps.max_wqe_sz_rq)); - rc = -EINVAL; - goto err_create_qp_rq_size; - } - - wqe_size_in_bytes = sizeof(golan_qp->sq.wqes[0]); - /* Calculate send queue size */ - if (wqe_size_in_bytes > be16_to_cpu(golan->caps.max_wqe_sz_sq)) { - DBGC (golan ,"%s send WQE size [%d] > max WQE size [%d]\n", __FUNCTION__, - wqe_size_in_bytes, - be16_to_cpu(golan->caps.max_wqe_sz_sq)); - rc = -EINVAL; - goto err_create_qp_sq_wqe_size; - } - golan_qp->sq.size = (qp->send.num_wqes * wqe_size_in_bytes); - max_qp_size_in_wqes = (1 << ((uint32_t)(golan->caps.log_max_qp_sz))); - if (qp->send.num_wqes > max_qp_size_in_wqes) { - DBGC (golan ,"%s send wq size [%d] > max wq size [%d]\n", __FUNCTION__, - golan_qp->sq.size, max_qp_size_in_wqes); - rc = -EINVAL; - goto err_create_qp_sq_size; - } - - golan_qp->size = golan_qp->sq.size + golan_qp->rq.size; - - /* allocate dma memory for WQEs (1 page is enough) - should change it */ - addr = golan_get_page ( &golan->pages ); - if (!addr) { - rc = -ENOMEM; - goto err_create_qp_wqe_alloc; - } - golan_qp->wqes = user_to_virt(addr, 0); - golan_qp->rq.wqes = golan_qp->wqes; - golan_qp->sq.wqes = golan_qp->wqes + golan_qp->rq.size;//(union golan_send_wqe *)& - //(((struct golan_recv_wqe_ud *)(golan_qp->wqes))[qp->recv.num_wqes]); - - if ( golan_qp->rq.grh_size ) { - golan_qp->rq.grh = ( golan_qp->wqes + - golan_qp->sq.size + - golan_qp->rq.size ); - } - - /* Invalidate all WQEs */ - data = &golan_qp->rq.wqes[0].data[0]; - for ( i = 0 ; i < ( golan_qp->rq.size / sizeof ( *data ) ); i++ ){ - data->lkey = cpu_to_be32 ( GOLAN_INVALID_LKEY ); - data++; - } - - golan_qp->doorbell_record = malloc_dma(sizeof(struct golan_qp_db), - sizeof(struct golan_qp_db)); - if (!golan_qp->doorbell_record) { - rc = -ENOMEM; - goto err_create_qp_db_alloc; - } - memset(golan_qp->doorbell_record, 0, sizeof(struct golan_qp_db)); - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_CREATE_QP, 0x0, - GEN_MBOX, NO_MBOX, - sizeof(struct golan_create_qp_mbox_in) + GOLAN_PAS_SIZE, - sizeof(struct golan_create_qp_mbox_out)); - - in = (struct golan_create_qp_mbox_in_data *)GET_INBOX(golan, GEN_MBOX); - - /* Fill the physical address of the page */ - in->pas[0] = USR_2_BE64_BUS(addr); - in->ctx.qp_counter_set_usr_page = cpu_to_be32(golan->uar.index); - - in->ctx.flags_pd = cpu_to_be32(golan->pdn); - in->ctx.flags = cpu_to_be32((golan_qp_type_to_st(qp->type) - << GOLAN_QP_CTX_ST_BIT) | - (GOLAN_QP_PM_MIGRATED << - GOLAN_QP_CTX_PM_STATE_BIT)); -// cgs set to 0, initialy. -// atomic mode - in->ctx.rq_size_stride = ((ilog2(qp->recv.num_wqes) << - GOLAN_QP_CTX_RQ_SIZE_BIT) | - (sizeof(golan_qp->rq.wqes[0]) / GOLAN_RECV_WQE_SIZE)); - in->ctx.sq_crq_size = cpu_to_be16(ilog2(golan_qp->sq.size / GOLAN_SEND_WQE_BB_SIZE) - << GOLAN_QP_CTX_SQ_SIZE_BIT); - in->ctx.cqn_send = cpu_to_be32(qp->send.cq->cqn); - in->ctx.cqn_recv = cpu_to_be32(qp->recv.cq->cqn); - in->ctx.db_rec_addr = VIRT_2_BE64_BUS(golan_qp->doorbell_record); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, GEN_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_create_qp_cmd ); - out = (struct golan_create_qp_mbox_out *)cmd->out; - - *qpn = (be32_to_cpu(out->qpn) & 0xffffff); - /* - * Hardware wants QPN written in big-endian order (after - * shifting) for send doorbell. Precompute this value to save - * a little bit when posting sends. - */ - golan_qp->doorbell_qpn = cpu_to_be32(*qpn << 8); - golan_qp->state = GOLAN_IB_QPS_RESET; - - ib_qp_set_drvdata(qp, golan_qp); - - return 0; - -err_create_qp_cmd: - free_dma(golan_qp->doorbell_record, sizeof(struct golan_qp_db)); -err_create_qp_db_alloc: - ufree((userptr_t)golan_qp->wqes); -err_create_qp_wqe_alloc: -err_create_qp_sq_size: -err_create_qp_sq_wqe_size: -err_create_qp_rq_size: - free ( golan_qp ); -err_create_qp: - return rc; -} - -/** - * Create queue pair - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @ret rc Return status code - */ -static int golan_create_qp(struct ib_device *ibdev, - struct ib_queue_pair *qp) -{ - int rc, qpn = -1; - - switch (qp->type) { - case IB_QPT_UD: - case IB_QPT_SMI: - case IB_QPT_GSI: - rc = golan_create_qp_aux(ibdev, qp, &qpn); - if (rc) { - DBG ( "%s Failed to create QP (rc = 0x%x)\n", __FUNCTION__, rc); - return rc; - } - qp->qpn = qpn; - - break; - case IB_QPT_ETH: - case IB_QPT_RC: - default: - DBG ( "%s unsupported QP type (0x%x)\n", __FUNCTION__, qp->type); - return -EINVAL; - } - - return 0; -} - -static int golan_modify_qp_rst_to_init(struct ib_device *ibdev, - struct ib_queue_pair *qp __unused, - struct golan_modify_qp_mbox_in_data *in) -{ - int rc = 0; - - in->ctx.qkey = cpu_to_be32((uint32_t)(qp->qkey)); - - in->ctx.pri_path.port = ibdev->port; - in->ctx.flags |= cpu_to_be32(GOLAN_QP_PM_MIGRATED << GOLAN_QP_CTX_PM_STATE_BIT); - in->ctx.pri_path.pkey_index = 0; /* default index */ - /* QK is 0 */ - /* QP cntr set 0 */ - return rc; -} - -static int golan_modify_qp_init_to_rtr(struct ib_device *ibdev __unused, - struct ib_queue_pair *qp __unused, - struct golan_modify_qp_mbox_in_data *in) -{ - int rc = 0; - - in->optparam = 0; - return rc; -} - -static int golan_modify_qp_rtr_to_rts(struct ib_device *ibdev __unused, - struct ib_queue_pair *qp __unused, - struct golan_modify_qp_mbox_in_data *in __unused) -{ - int rc = 0; - - in->optparam = 0; - /* In good flow psn in 0 */ - return rc; -} - -static int golan_modify_qp_to_rst(struct ib_device *ibdev, - struct ib_queue_pair *qp) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_queue_pair *golan_qp = ib_qp_get_drvdata(qp); - struct golan_cmd_layout *cmd; - int rc; - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_2RST_QP, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_modify_qp_mbox_in), - sizeof(struct golan_modify_qp_mbox_out)); - ((struct golan_modify_qp_mbox_in *)(cmd->in))->qpn = cpu_to_be32(qp->qpn); - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_modify_qp_2rst_cmd ); - - golan_qp->state = GOLAN_IB_QPS_RESET; - DBGC( golan , "%s QP number 0x%lx was modified to RESET\n", - __FUNCTION__, qp->qpn); - - return 0; - -err_modify_qp_2rst_cmd: - DBGC (golan ,"%s Failed to modify QP number 0x%lx (rc = 0x%x)\n", - __FUNCTION__, qp->qpn, rc); - return rc; -} - -static int (*golan_modify_qp_methods[])(struct ib_device *ibdev, - struct ib_queue_pair *qp, - struct golan_modify_qp_mbox_in_data *in) = { - - [GOLAN_IB_QPS_RESET] = golan_modify_qp_rst_to_init, - [GOLAN_IB_QPS_INIT] = golan_modify_qp_init_to_rtr, - [GOLAN_IB_QPS_RTR] = golan_modify_qp_rtr_to_rts -}; - -static int golan_modify_qp(struct ib_device *ibdev, - struct ib_queue_pair *qp) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_queue_pair *golan_qp = ib_qp_get_drvdata(qp); - struct golan_modify_qp_mbox_in_data *in; - struct golan_cmd_layout *cmd; - enum golan_ib_qp_state prev_state; - int rc; - int modify_cmd[] = {GOLAN_CMD_OP_RST2INIT_QP, - GOLAN_CMD_OP_INIT2RTR_QP, - GOLAN_CMD_OP_RTR2RTS_QP}; - - while (golan_qp->state < GOLAN_IB_QPS_RTS) { - prev_state = golan_qp->state; - cmd = write_cmd(golan, DEF_CMD_IDX, modify_cmd[golan_qp->state], 0x0, - GEN_MBOX, NO_MBOX, - sizeof(struct golan_modify_qp_mbox_in), - sizeof(struct golan_modify_qp_mbox_out)); - - in = (struct golan_modify_qp_mbox_in_data *)GET_INBOX(golan, GEN_MBOX); - ((struct golan_modify_qp_mbox_in *)(cmd->in))->qpn = cpu_to_be32(qp->qpn); - rc = golan_modify_qp_methods[golan_qp->state](ibdev, qp, in); - if (rc) { - goto err_modify_qp_fill_inbox; - } -// in->ctx.qp_counter_set_usr_page = cpu_to_be32(golan->uar.index); - rc = send_command_and_wait(golan, DEF_CMD_IDX, GEN_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_modify_qp_cmd ); - - ++(golan_qp->state); - - DBGC( golan , "%s QP number 0x%lx was modified from %s to %s\n", - __FUNCTION__, qp->qpn, golan_qp_state_as_string[prev_state], - golan_qp_state_as_string[golan_qp->state]); - } - - DBGC( golan , "%s QP number 0x%lx is ready to receive/send packets.\n", - __FUNCTION__, qp->qpn); - return 0; - -err_modify_qp_cmd: -err_modify_qp_fill_inbox: - DBGC (golan ,"%s Failed to modify QP number 0x%lx (rc = 0x%x)\n", - __FUNCTION__, qp->qpn, rc); - return rc; -} - -/** - * Destroy queue pair - * - * @v ibdev Infiniband device - * @v qp Queue pair - */ -static void golan_destroy_qp(struct ib_device *ibdev, - struct ib_queue_pair *qp) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_queue_pair *golan_qp = ib_qp_get_drvdata(qp); - struct golan_cmd_layout *cmd; - unsigned long qpn = qp->qpn; - int rc; - - DBGC (golan, "%s in\n", __FUNCTION__); - - if (golan_qp->state != GOLAN_IB_QPS_RESET) { - if (golan_modify_qp_to_rst(ibdev, qp)) { - DBGC (golan ,"%s Failed to modify QP 0x%lx to RESET\n", __FUNCTION__, - qp->qpn); - } - } - - if (qp->recv.cq) { - golan_cq_clean(qp->recv.cq); - } - if (qp->send.cq && (qp->send.cq != qp->recv.cq)) { - golan_cq_clean(qp->send.cq); - } - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_DESTROY_QP, 0x0, - NO_MBOX, NO_MBOX, - sizeof(struct golan_destroy_qp_mbox_in), - sizeof(struct golan_destroy_qp_mbox_out)); - ((struct golan_destroy_qp_mbox_in *)(cmd->in))->qpn = cpu_to_be32(qpn); - rc = send_command_and_wait(golan, DEF_CMD_IDX, NO_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - qp->qpn = 0; - - ib_qp_set_drvdata(qp, NULL); - free_dma(golan_qp->doorbell_record, sizeof(struct golan_qp_db)); - ufree((userptr_t)golan_qp->wqes); - free(golan_qp); - - DBGC( golan ,"%s QP 0x%lx was destroyed\n", __FUNCTION__, qpn); -} - -/** - * Calculate transmission rate - * - * @v av Address vector - * @ret golan_rate Golan rate - */ -static unsigned int golan_rate(enum ib_rate rate) { - return (((rate >= IB_RATE_2_5) && (rate <= IB_RATE_120)) ? (rate + 5) : 0); -} - -/** - * Post send work queue entry - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v av Address vector - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int golan_post_send(struct ib_device *ibdev, - struct ib_queue_pair *qp, - struct ib_address_vector *av, - struct io_buffer *iobuf) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_queue_pair *golan_qp = ib_qp_get_drvdata(qp); - struct golan_send_wqe_ud *wqe = NULL; - struct golan_av *datagram = NULL; - unsigned long wqe_idx_mask; - unsigned long wqe_idx; - struct golan_wqe_data_seg *data = NULL; - struct golan_wqe_ctrl_seg *ctrl = NULL; -// static uint8_t toggle = 0; - - - wqe_idx_mask = (qp->send.num_wqes - 1); - wqe_idx = (qp->send.next_idx & wqe_idx_mask); - if (qp->send.iobufs[wqe_idx]) { - DBGC (golan ,"%s Send queue of QPN 0x%lx is full\n", __FUNCTION__, qp->qpn); - return -ENOMEM; - } - - qp->send.iobufs[wqe_idx] = iobuf; - - // change to this - //wqe_size_in_octa_words = golan_qp->sq.wqe_size_in_wqebb >> 4; - - wqe = &golan_qp->sq.wqes[wqe_idx].ud; - - //CHECK HW OWNERSHIP BIT ??? - - memset(wqe, 0, sizeof(*wqe)); - - ctrl = &wqe->ctrl; - ctrl->opmod_idx_opcode = cpu_to_be32(GOLAN_SEND_OPCODE | - ((u32)(golan_qp->sq.next_idx) << - GOLAN_WQE_CTRL_WQE_IDX_BIT)); - ctrl->qpn_ds = cpu_to_be32(GOLAN_SEND_UD_WQE_SIZE >> 4) | - golan_qp->doorbell_qpn; - ctrl->fm_ce_se = 0x8;//10 - 0 - 0 - data = &wqe->data; - data->byte_count = cpu_to_be32(iob_len(iobuf)); - data->lkey = cpu_to_be32(golan->mkey); - data->addr = VIRT_2_BE64_BUS(iobuf->data); - - datagram = &wqe->datagram; - datagram->key.qkey.qkey = cpu_to_be32(av->qkey); - datagram->dqp_dct = cpu_to_be32((1 << 31) | av->qpn); - datagram->stat_rate_sl = ((golan_rate(av->rate) << 4) | av->sl); - datagram->fl_mlid = (ibdev->lid & 0x007f); /* take only the 7 low bits of the LID */ - datagram->rlid = cpu_to_be16(av->lid); - datagram->grh_gid_fl = cpu_to_be32(av->gid_present << 30); - memcpy(datagram->rgid, av->gid.bytes, 16 /* sizeof(datagram->rgid) */); - - /* - * Make sure that descriptors are written before - * updating doorbell record and ringing the doorbell - */ - ++(qp->send.next_idx); - golan_qp->sq.next_idx = (golan_qp->sq.next_idx + GOLAN_WQEBBS_PER_SEND_UD_WQE); - golan_qp->doorbell_record->send_db = cpu_to_be16(golan_qp->sq.next_idx); - wmb(); - writeq(*((__be64 *)ctrl), golan->uar.virt + 0x800);// + -// ((toggle++ & 0x1) ? 0x100 : 0x0)); - return 0; -} - -/** - * Post receive work queue entry - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int golan_post_recv(struct ib_device *ibdev, - struct ib_queue_pair *qp, - struct io_buffer *iobuf) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_queue_pair *golan_qp = ib_qp_get_drvdata(qp); - struct ib_work_queue *wq = &qp->recv; - struct golan_recv_wqe_ud *wqe; - struct ib_global_route_header *grh; - struct golan_wqe_data_seg *data; - unsigned int wqe_idx_mask; - - /* Allocate work queue entry */ - wqe_idx_mask = (wq->num_wqes - 1); - if (wq->iobufs[wq->next_idx & wqe_idx_mask]) { - DBGC (golan ,"%s Receive queue of QPN 0x%lx is full\n", __FUNCTION__, qp->qpn); - return -ENOMEM; - } - - wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf; - wqe = & golan_qp->rq.wqes[wq->next_idx & wqe_idx_mask]; - - memset(wqe, 0, sizeof(*wqe)); - data = &wqe->data[0]; - if ( golan_qp->rq.grh ) { - grh = &golan_qp->rq.grh[wq->next_idx & wqe_idx_mask]; - data->byte_count = cpu_to_be32 ( sizeof ( *grh ) ); - data->lkey = cpu_to_be32 ( golan->mkey ); - data->addr = VIRT_2_BE64_BUS ( grh ); - data++; - } - - data->byte_count = cpu_to_be32(iob_tailroom(iobuf)); - data->lkey = cpu_to_be32(golan->mkey); - data->addr = VIRT_2_BE64_BUS(iobuf->data); - - ++wq->next_idx; - - /* - * Make sure that descriptors are written before - * updating doorbell record and ringing the doorbell - */ - wmb(); - golan_qp->doorbell_record->recv_db = cpu_to_be16(qp->recv.next_idx & 0xffff); - - return 0; -} - -static int golan_query_vport_context ( struct ib_device *ibdev ) { - struct golan *golan = ib_get_drvdata ( ibdev ); - struct golan_cmd_layout *cmd; - struct golan_query_hca_vport_context_inbox *in; - struct golan_query_hca_vport_context_data *context_data; - int rc; - - cmd = write_cmd ( golan, DEF_CMD_IDX, GOLAN_CMD_OP_QUERY_HCA_VPORT_CONTEXT, - 0x0, GEN_MBOX, GEN_MBOX, - sizeof(struct golan_query_hca_vport_context_inbox), - sizeof(struct golan_query_hca_vport_context_outbox) ); - - in = GOLAN_MBOX_IN ( cmd, in ); - in->port_num = (u8)ibdev->port; - - rc = send_command_and_wait ( golan, DEF_CMD_IDX, GEN_MBOX, GEN_MBOX, __FUNCTION__ ); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_query_vport_context_cmd ); - - context_data = (struct golan_query_hca_vport_context_data *)( GET_OUTBOX ( golan, GEN_MBOX ) ); - - ibdev->node_guid.dwords[0] = context_data->node_guid[0]; - ibdev->node_guid.dwords[1] = context_data->node_guid[1]; - ibdev->lid = be16_to_cpu( context_data->lid ); - ibdev->sm_lid = be16_to_cpu( context_data->sm_lid ); - ibdev->sm_sl = context_data->sm_sl; - ibdev->port_state = context_data->port_state; - - return 0; -err_query_vport_context_cmd: - DBGC (golan ,"%s [%d] out\n", __FUNCTION__, rc); - return rc; -} - - -static int golan_query_vport_gid ( struct ib_device *ibdev ) { - struct golan *golan = ib_get_drvdata( ibdev ); - struct golan_cmd_layout *cmd; - struct golan_query_hca_vport_gid_inbox *in; - union ib_gid *ib_gid; - int rc; - - cmd = write_cmd( golan, DEF_CMD_IDX, GOLAN_CMD_OP_QUERY_HCA_VPORT_GID, - 0x0, GEN_MBOX, GEN_MBOX, - sizeof(struct golan_query_hca_vport_gid_inbox), - sizeof(struct golan_query_hca_vport_gid_outbox) ); - - in = GOLAN_MBOX_IN ( cmd, in ); - in->port_num = (u8)ibdev->port; - in->gid_index = 0; - rc = send_command_and_wait ( golan, DEF_CMD_IDX, GEN_MBOX, GEN_MBOX, __FUNCTION__ ); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_query_vport_gid_cmd ); - - ib_gid = (union ib_gid *)( GET_OUTBOX ( golan, GEN_MBOX ) ); - - memcpy ( &ibdev->gid, ib_gid, sizeof(ibdev->gid) ); - - return 0; -err_query_vport_gid_cmd: - DBGC ( golan, "%s [%d] out\n", __FUNCTION__, rc); - return rc; -} - -static int golan_query_vport_pkey ( struct ib_device *ibdev ) { - struct golan *golan = ib_get_drvdata ( ibdev ); - struct golan_cmd_layout *cmd; - struct golan_query_hca_vport_pkey_inbox *in; - //struct golan_query_hca_vport_pkey_data *pkey_table; - int pkey_table_size_in_entries = (1 << (7 + golan->caps.pkey_table_size)); - int rc; - - cmd = write_cmd ( golan, DEF_CMD_IDX, GOLAN_CMD_OP_QUERY_HCA_VPORT_PKEY, - 0x0, GEN_MBOX, GEN_MBOX, - sizeof(struct golan_query_hca_vport_pkey_inbox), - sizeof(struct golan_outbox_hdr) + 8 + - sizeof(struct golan_query_hca_vport_pkey_data) * pkey_table_size_in_entries ); - - in = GOLAN_MBOX_IN ( cmd, in ); - in->port_num = (u8)ibdev->port; - in->pkey_index = 0xffff; - rc = send_command_and_wait ( golan, DEF_CMD_IDX, GEN_MBOX, GEN_MBOX, __FUNCTION__ ); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_query_vport_pkey_cmd ); - - //pkey_table = (struct golan_query_hca_vport_pkey_data *)( GET_OUTBOX ( golan, GEN_MBOX ) ); - - return 0; -err_query_vport_pkey_cmd: - DBGC (golan ,"%s [%d] out\n", __FUNCTION__, rc); - return rc; -} - -static int golan_get_ib_info ( struct ib_device *ibdev ) { - int rc; - - rc = golan_query_vport_context ( ibdev ); - if ( rc != 0 ) { - DBG ( "golan_get_ib_info: golan_query_vport_context Failed (rc = %d)\n",rc ); - goto err_query_vport_context; - } - - rc = golan_query_vport_gid ( ibdev ); - if ( rc != 0 ) { - DBG ( "golan_get_ib_info: golan_query_vport_gid Failed (rc = %d)\n",rc ); - goto err_query_vport_gid; - } - - rc = golan_query_vport_pkey ( ibdev ); - if ( rc != 0 ) { - DBG ( "golan_get_ib_info: golan_query_vport_pkey Failed (rc = %d)\n",rc ); - goto err_query_vport_pkey; - } - return rc; -err_query_vport_pkey: -err_query_vport_gid: -err_query_vport_context: - DBG ( "%s [%d] out\n", __FUNCTION__, rc); - return rc; -} - -static int golan_complete(struct ib_device *ibdev, - struct ib_completion_queue *cq, - struct golan_cqe64 *cqe64) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct ib_work_queue *wq; - struct golan_queue_pair *golan_qp; - struct ib_queue_pair *qp; - struct io_buffer *iobuf = NULL; - struct ib_address_vector recv_dest; - struct ib_address_vector recv_source; - struct ib_global_route_header *grh; - struct golan_err_cqe *err_cqe64; - int gid_present, idx; - u16 wqe_ctr; - uint8_t opcode; - static int error_state; - uint32_t qpn = be32_to_cpu(cqe64->sop_drop_qpn) & 0xffffff; - int is_send = 0; - size_t len; - - opcode = cqe64->op_own >> GOLAN_CQE_OPCODE_BIT; - DBGC2( golan , "%s completion with opcode 0x%x\n", __FUNCTION__, opcode); - - if (opcode == GOLAN_CQE_REQ || opcode == GOLAN_CQE_REQ_ERR) { - is_send = 1; - } else { - is_send = 0; - } - if (opcode == GOLAN_CQE_REQ_ERR || opcode == GOLAN_CQE_RESP_ERR) { - err_cqe64 = (struct golan_err_cqe *)cqe64; - int i = 0; - if (!error_state++) { - DBGC (golan ,"\n"); - for ( i = 0 ; i < 16 ; i += 2 ) { - DBGC (golan ,"%x %x\n", - be32_to_cpu(((uint32_t *)(err_cqe64))[i]), - be32_to_cpu(((uint32_t *)(err_cqe64))[i + 1])); - } - DBGC (golan ,"CQE with error: Syndrome(0x%x), VendorSynd(0x%x), HW_SYN(0x%x)\n", - err_cqe64->syndrome, err_cqe64->vendor_err_synd, - err_cqe64->hw_syndrom); - } - } - /* Identify work queue */ - wq = ib_find_wq(cq, qpn, is_send); - if (!wq) { - DBGC (golan ,"%s unknown %s QPN 0x%x in CQN 0x%lx\n", - __FUNCTION__, (is_send ? "send" : "recv"), qpn, cq->cqn); - return -EINVAL; - } - - qp = wq->qp; - golan_qp = ib_qp_get_drvdata ( qp ); - - wqe_ctr = be16_to_cpu(cqe64->wqe_counter); - if (is_send) { - wqe_ctr &= ((GOLAN_WQEBBS_PER_SEND_UD_WQE * wq->num_wqes) - 1); - idx = wqe_ctr / GOLAN_WQEBBS_PER_SEND_UD_WQE; - } else { - idx = wqe_ctr & (wq->num_wqes - 1); - } - - iobuf = wq->iobufs[idx]; - if (!iobuf) { - DBGC (golan ,"%s IO Buffer 0x%x not found in QPN 0x%x\n", - __FUNCTION__, idx, qpn); - return -EINVAL; - } - wq->iobufs[idx] = NULL; - - if (is_send) { - ib_complete_send(ibdev, qp, iobuf, (opcode == GOLAN_CQE_REQ_ERR)); - } else { - len = be32_to_cpu(cqe64->byte_cnt); - memset(&recv_dest, 0, sizeof(recv_dest)); - recv_dest.qpn = qpn; - /* Construct address vector */ - memset(&recv_source, 0, sizeof(recv_source)); - switch (qp->type) { - case IB_QPT_SMI: - case IB_QPT_GSI: - case IB_QPT_UD: - /* Locate corresponding GRH */ - assert ( golan_qp->rq.grh != NULL ); - grh = &golan_qp->rq.grh[ idx ]; - - recv_source.qpn = be32_to_cpu(cqe64->flags_rqpn) & 0xffffff; - recv_source.lid = be16_to_cpu(cqe64->slid); - recv_source.sl = (be32_to_cpu(cqe64->flags_rqpn) >> 24) & 0xf; - gid_present = (be32_to_cpu(cqe64->flags_rqpn) >> 28) & 3; - if (!gid_present) { - recv_dest.gid_present = recv_source.gid_present = 0; - } else { - recv_dest.gid_present = recv_source.gid_present = 1; - //if (recv_source.gid_present == 0x1) { - memcpy(&recv_source.gid, &grh->sgid, sizeof(recv_source.gid)); - memcpy(&recv_dest.gid, &grh->dgid, sizeof(recv_dest.gid)); - //} else { // recv_source.gid_present = 0x3 - /* GRH is located in the upper 64 byte of the CQE128 - * currently not supported */ - //; - //} - } - len -= sizeof ( *grh ); - break; - case IB_QPT_RC: - case IB_QPT_ETH: - default: - DBGC (golan ,"%s Unsupported QP type (0x%x)\n", __FUNCTION__, qp->type); - return -EINVAL; - } - assert(len <= iob_tailroom(iobuf)); - iob_put(iobuf, len); - ib_complete_recv(ibdev, qp, &recv_dest, &recv_source, iobuf, (opcode == GOLAN_CQE_RESP_ERR)); - } - return 0; -} - -static int golan_is_hw_ownership(struct ib_completion_queue *cq, - struct golan_cqe64 *cqe64) -{ - return ((cqe64->op_own & GOLAN_CQE_OWNER_MASK) != - ((cq->next_idx >> ilog2(cq->num_cqes)) & 1)); -} -static void golan_poll_cq(struct ib_device *ibdev, - struct ib_completion_queue *cq) -{ - unsigned int i; - int rc = 0; - unsigned int cqe_idx_mask; - struct golan_cqe64 *cqe64; - struct golan_completion_queue *golan_cq = ib_cq_get_drvdata(cq); - struct golan *golan = ib_get_drvdata(ibdev); - - for (i = 0; i < cq->num_cqes; ++i) { - /* Look for completion entry */ - cqe_idx_mask = (cq->num_cqes - 1); - cqe64 = &golan_cq->cqes[cq->next_idx & cqe_idx_mask]; - /* temporary valid only for 64 byte CQE */ - if (golan_is_hw_ownership(cq, cqe64) || - ((cqe64->op_own >> GOLAN_CQE_OPCODE_BIT) == - GOLAN_CQE_OPCODE_NOT_VALID)) { - break; /* HW ownership */ - } - - DBGC2( golan , "%s CQN 0x%lx [%ld] \n", __FUNCTION__, cq->cqn, cq->next_idx); - /* - * Make sure we read CQ entry contents after we've checked the - * ownership bit. (PRM - 6.5.3.2) - */ - rmb(); - rc = golan_complete(ibdev, cq, cqe64); - if (rc != 0) { - DBGC (golan ,"%s CQN 0x%lx failed to complete\n", __FUNCTION__, cq->cqn); - } - - /* Update completion queue's index */ - cq->next_idx++; - - /* Update doorbell record */ - *(golan_cq->doorbell_record) = cpu_to_be32(cq->next_idx & 0xffffff); - } -} - -static const char *golan_eqe_type_str(u8 type) -{ - switch (type) { - case GOLAN_EVENT_TYPE_COMP: - return "GOLAN_EVENT_TYPE_COMP"; - case GOLAN_EVENT_TYPE_PATH_MIG: - return "GOLAN_EVENT_TYPE_PATH_MIG"; - case GOLAN_EVENT_TYPE_COMM_EST: - return "GOLAN_EVENT_TYPE_COMM_EST"; - case GOLAN_EVENT_TYPE_SQ_DRAINED: - return "GOLAN_EVENT_TYPE_SQ_DRAINED"; - case GOLAN_EVENT_TYPE_SRQ_LAST_WQE: - return "GOLAN_EVENT_TYPE_SRQ_LAST_WQE"; - case GOLAN_EVENT_TYPE_SRQ_RQ_LIMIT: - return "GOLAN_EVENT_TYPE_SRQ_RQ_LIMIT"; - case GOLAN_EVENT_TYPE_CQ_ERROR: - return "GOLAN_EVENT_TYPE_CQ_ERROR"; - case GOLAN_EVENT_TYPE_WQ_CATAS_ERROR: - return "GOLAN_EVENT_TYPE_WQ_CATAS_ERROR"; - case GOLAN_EVENT_TYPE_PATH_MIG_FAILED: - return "GOLAN_EVENT_TYPE_PATH_MIG_FAILED"; - case GOLAN_EVENT_TYPE_WQ_INVAL_REQ_ERROR: - return "GOLAN_EVENT_TYPE_WQ_INVAL_REQ_ERROR"; - case GOLAN_EVENT_TYPE_WQ_ACCESS_ERROR: - return "GOLAN_EVENT_TYPE_WQ_ACCESS_ERROR"; - case GOLAN_EVENT_TYPE_SRQ_CATAS_ERROR: - return "GOLAN_EVENT_TYPE_SRQ_CATAS_ERROR"; - case GOLAN_EVENT_TYPE_INTERNAL_ERROR: - return "GOLAN_EVENT_TYPE_INTERNAL_ERROR"; - case GOLAN_EVENT_TYPE_PORT_CHANGE: - return "GOLAN_EVENT_TYPE_PORT_CHANGE"; - case GOLAN_EVENT_TYPE_GPIO_EVENT: - return "GOLAN_EVENT_TYPE_GPIO_EVENT"; - case GOLAN_EVENT_TYPE_REMOTE_CONFIG: - return "GOLAN_EVENT_TYPE_REMOTE_CONFIG"; - case GOLAN_EVENT_TYPE_DB_BF_CONGESTION: - return "GOLAN_EVENT_TYPE_DB_BF_CONGESTION"; - case GOLAN_EVENT_TYPE_STALL_EVENT: - return "GOLAN_EVENT_TYPE_STALL_EVENT"; - case GOLAN_EVENT_TYPE_CMD: - return "GOLAN_EVENT_TYPE_CMD"; - case GOLAN_EVENT_TYPE_PAGE_REQUEST: - return "GOLAN_EVENT_TYPE_PAGE_REQUEST"; - default: - return "Unrecognized event"; - } -} - -static const char *golan_eqe_port_subtype_str(u8 subtype) -{ - switch (subtype) { - case GOLAN_PORT_CHANGE_SUBTYPE_DOWN: - return "GOLAN_PORT_CHANGE_SUBTYPE_DOWN"; - case GOLAN_PORT_CHANGE_SUBTYPE_ACTIVE: - return "GOLAN_PORT_CHANGE_SUBTYPE_ACTIVE"; - case GOLAN_PORT_CHANGE_SUBTYPE_INITIALIZED: - return "GOLAN_PORT_CHANGE_SUBTYPE_INITIALIZED"; - case GOLAN_PORT_CHANGE_SUBTYPE_LID: - return "GOLAN_PORT_CHANGE_SUBTYPE_LID"; - case GOLAN_PORT_CHANGE_SUBTYPE_PKEY: - return "GOLAN_PORT_CHANGE_SUBTYPE_PKEY"; - case GOLAN_PORT_CHANGE_SUBTYPE_GUID: - return "GOLAN_PORT_CHANGE_SUBTYPE_GUID"; - case GOLAN_PORT_CHANGE_SUBTYPE_CLIENT_REREG: - return "GOLAN_PORT_CHANGE_SUBTYPE_CLIENT_REREG"; - default: - return "Unrecognized event"; - } -} - -/** - * Update Infiniband parameters using Commands - * - * @v ibdev Infiniband device - * @ret rc Return status code - */ -static int golan_ib_update ( struct ib_device *ibdev ) { - int rc; - - /* Get IB parameters */ - if ( ( rc = golan_get_ib_info ( ibdev ) ) != 0 ) - return rc; - - /* Notify Infiniband core of potential link state change */ - ib_link_state_changed ( ibdev ); - - return 0; -} - -static inline void golan_handle_port_event(struct golan *golan, struct golan_eqe *eqe) -{ - struct ib_device *ibdev; - u8 port; - - port = (eqe->data.port.port >> 4) & 0xf; - ibdev = golan->ports[port - 1].ibdev; - - if ( ! ib_is_open ( ibdev ) ) - return; - - switch (eqe->sub_type) { - case GOLAN_PORT_CHANGE_SUBTYPE_CLIENT_REREG: - case GOLAN_PORT_CHANGE_SUBTYPE_ACTIVE: - golan_ib_update ( ibdev ); - case GOLAN_PORT_CHANGE_SUBTYPE_DOWN: - case GOLAN_PORT_CHANGE_SUBTYPE_LID: - case GOLAN_PORT_CHANGE_SUBTYPE_PKEY: - case GOLAN_PORT_CHANGE_SUBTYPE_GUID: - case GOLAN_PORT_CHANGE_SUBTYPE_INITIALIZED: - DBGC( golan , "%s event %s(%d) (sub event %s(%d))arrived on port %d\n", - __FUNCTION__, golan_eqe_type_str(eqe->type), eqe->type, - golan_eqe_port_subtype_str(eqe->sub_type), - eqe->sub_type, port); - break; - default: - DBGC (golan ,"%s Port event with unrecognized subtype: port %d, sub_type %d\n", - __FUNCTION__, port, eqe->sub_type); - } -} - -static struct golan_eqe *golan_next_eqe_sw(struct golan_event_queue *eq) -{ - uint32_t entry = (eq->cons_index & (GOLAN_NUM_EQES - 1)); - struct golan_eqe *eqe = &(eq->eqes[entry]); - return ((eqe->owner != ((eq->cons_index >> ilog2(GOLAN_NUM_EQES)) & 1)) ? NULL : eqe); -} - - -/** - * Poll event queue - * - * @v ibdev Infiniband device - */ -static void golan_poll_eq(struct ib_device *ibdev) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_event_queue *eq = &(golan->eq); - struct golan_eqe *eqe; - u32 cqn; - int counter = 0; - - while ((eqe = golan_next_eqe_sw(eq)) && (counter < GOLAN_NUM_EQES)) { - /* - * Make sure we read EQ entry contents after we've - * checked the ownership bit. - */ - rmb(); - - DBGC( golan , "%s eqn %d, eqe type %s\n", __FUNCTION__, eq->eqn, - golan_eqe_type_str(eqe->type)); - switch (eqe->type) { - case GOLAN_EVENT_TYPE_COMP: - /* We dont need to handle completion events since we - * poll all the CQs after polling the EQ */ - break; - case GOLAN_EVENT_TYPE_PATH_MIG: - case GOLAN_EVENT_TYPE_COMM_EST: - case GOLAN_EVENT_TYPE_SQ_DRAINED: - case GOLAN_EVENT_TYPE_SRQ_LAST_WQE: - case GOLAN_EVENT_TYPE_WQ_CATAS_ERROR: - case GOLAN_EVENT_TYPE_PATH_MIG_FAILED: - case GOLAN_EVENT_TYPE_WQ_INVAL_REQ_ERROR: - case GOLAN_EVENT_TYPE_WQ_ACCESS_ERROR: - case GOLAN_EVENT_TYPE_SRQ_RQ_LIMIT: - case GOLAN_EVENT_TYPE_SRQ_CATAS_ERROR: - DBGC( golan , "%s event %s(%d) arrived\n", __FUNCTION__, - golan_eqe_type_str(eqe->type), eqe->type); - break; - case GOLAN_EVENT_TYPE_CMD: -// golan_cmd_comp_handler(be32_to_cpu(eqe->data.cmd.vector)); - break; - case GOLAN_EVENT_TYPE_PORT_CHANGE: - golan_handle_port_event(golan, eqe); - break; - case GOLAN_EVENT_TYPE_CQ_ERROR: - cqn = be32_to_cpu(eqe->data.cq_err.cqn) & 0xffffff; - DBGC (golan ,"CQ error on CQN 0x%x, syndrom 0x%x\n", - cqn, eqe->data.cq_err.syndrome); -// mlx5_cq_event(dev, cqn, eqe->type); - break; - case GOLAN_EVENT_TYPE_PAGE_REQUEST: - { - /* we should check if we get this event while we - * waiting for a command */ - u16 func_id = be16_to_cpu(eqe->data.req_pages.func_id); - s16 npages = be16_to_cpu(eqe->data.req_pages.num_pages); - - DBGC (golan ,"%s page request for func 0x%x, napges %d\n", - __FUNCTION__, func_id, npages); - golan_provide_pages(golan, npages, func_id); - } - break; - default: - DBGC (golan ,"%s Unhandled event 0x%x on EQ 0x%x\n", __FUNCTION__, - eqe->type, eq->eqn); - break; - } - - ++eq->cons_index; - golan_eq_update_ci(eq, GOLAN_EQ_UNARMED); - ++counter; - } -} - -/** - * Attach to multicast group - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v gid Multicast GID - * @ret rc Return status code - */ -static int golan_mcast_attach(struct ib_device *ibdev, - struct ib_queue_pair *qp, - union ib_gid *gid) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_cmd_layout *cmd; - int rc; - - if ( qp == NULL ) { - DBGC( golan, "%s: Invalid pointer, could not attach QPN to MCG\n", - __FUNCTION__ ); - return -EFAULT; - } - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_ATTACH_TO_MCG, 0x0, - GEN_MBOX, NO_MBOX, - sizeof(struct golan_attach_mcg_mbox_in), - sizeof(struct golan_attach_mcg_mbox_out)); - ((struct golan_attach_mcg_mbox_in *)(cmd->in))->qpn = cpu_to_be32(qp->qpn); - - memcpy(GET_INBOX(golan, GEN_MBOX), gid, sizeof(*gid)); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, GEN_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_CHECK_RC_AND_CMD_STATUS( err_attach_to_mcg_cmd ); - - DBGC( golan , "%s: QPN 0x%lx was attached to MCG\n", __FUNCTION__, qp->qpn); - return 0; -err_attach_to_mcg_cmd: - DBGC (golan ,"%s [%d] out\n", __FUNCTION__, rc); - return rc; -} - -/** - * Detach from multicast group - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v gid Multicast GID - * @ret rc Return status code - */ -static void golan_mcast_detach(struct ib_device *ibdev, - struct ib_queue_pair *qp, - union ib_gid *gid) -{ - struct golan *golan = ib_get_drvdata(ibdev); - struct golan_cmd_layout *cmd; - int rc; - - cmd = write_cmd(golan, DEF_CMD_IDX, GOLAN_CMD_OP_DETACH_FROM_MCG, 0x0, - GEN_MBOX, NO_MBOX, - sizeof(struct golan_detach_mcg_mbox_in), - sizeof(struct golan_detach_mcg_mbox_out)); - ((struct golan_detach_mcg_mbox_in *)(cmd->in))->qpn = cpu_to_be32(qp->qpn); - - memcpy(GET_INBOX(golan, GEN_MBOX), gid, sizeof(*gid)); - - rc = send_command_and_wait(golan, DEF_CMD_IDX, GEN_MBOX, NO_MBOX, __FUNCTION__); - GOLAN_PRINT_RC_AND_CMD_STATUS; - - DBGC( golan , "%s: QPN 0x%lx was detached from MCG\n", __FUNCTION__, qp->qpn); -} - -/** - * Inform embedded subnet management agent of a received MAD - * - * @v ibdev Infiniband device - * @v mad MAD - * @ret rc Return status code - */ -static int golan_inform_sma(struct ib_device *ibdev, - union ib_mad *mad) -{ - if (!ibdev || !mad) { - return 1; - } - - return 0; -} - -static int golan_register_ibdev(struct golan_port *port) -{ - struct ib_device *ibdev = port->ibdev; - int rc; - - golan_get_ib_info ( ibdev ); - /* Register Infiniband device */ - if ((rc = register_ibdev(ibdev)) != 0) { - DBG ( "%s port %d could not register IB device: (rc = %d)\n", - __FUNCTION__, ibdev->port, rc); - return rc; - } - - port->netdev = ipoib_netdev( ibdev ); - - return 0; -} - -static inline void golan_bring_down(struct golan *golan) -{ - - DBGC(golan, "%s: start\n", __FUNCTION__); - - if (~golan->flags & GOLAN_OPEN) { - DBGC(golan, "%s: end (already closed)\n", __FUNCTION__); - return; - } - - golan_destroy_mkey(golan); - golan_dealloc_pd(golan); - golan_destory_eq(golan); - golan_dealloc_uar(golan); - golan_teardown_hca(golan, GOLAN_TEARDOWN_GRACEFUL); - golan_handle_pages(golan, GOLAN_REG_PAGES , GOLAN_PAGES_TAKE); - golan_disable_hca(golan); - golan_cmd_uninit(golan); - golan->flags &= ~GOLAN_OPEN; - DBGC(golan, "%s: end\n", __FUNCTION__); -} - -static int golan_set_link_speed ( struct golan *golan ){ - mlx_utils utils; - mlx_status status; - int i = 0; - - memset ( &utils, 0, sizeof ( utils ) ); - - status = mlx_utils_init ( &utils, golan->pci ); - MLX_CHECK_STATUS ( golan->pci, status, utils_init_err, "mlx_utils_init failed" ); - - status = mlx_pci_gw_init ( &utils ); - MLX_CHECK_STATUS ( golan->pci, status, pci_gw_init_err, "mlx_pci_gw_init failed" ); - - for ( i = 0; i < golan->caps.num_ports; ++i ) { - status = mlx_set_link_speed( &utils, i + 1, LINK_SPEED_IB, LINK_SPEED_SDR ); - MLX_CHECK_STATUS ( golan->pci, status, set_link_speed_err, "mlx_set_link_speed failed" ); - } - -set_link_speed_err: - mlx_pci_gw_teardown( &utils ); -pci_gw_init_err: -utils_init_err: - return status; -} - -static inline int golan_bring_up(struct golan *golan) -{ - int rc = 0; - DBGC(golan, "%s\n", __FUNCTION__); - - if (golan->flags & GOLAN_OPEN) - return 0; - - if (( rc = golan_cmd_init(golan) )) - goto out; - - if (( rc = golan_core_enable_hca(golan) )) - goto cmd_uninit; - - /* Query for need for boot pages */ - if (( rc = golan_handle_pages(golan, GOLAN_BOOT_PAGES, GOLAN_PAGES_GIVE) )) - goto disable; - - if (( rc = golan_qry_hca_cap(golan) )) - goto pages; - - if (( rc = golan_set_hca_cap(golan) )) - goto pages; - - if (( rc = golan_handle_pages(golan, GOLAN_INIT_PAGES, GOLAN_PAGES_GIVE) )) - goto pages; - - if (( rc = golan_set_link_speed ( golan ) )) - goto pages_teardown; - - //Reg Init? - if (( rc = golan_hca_init(golan) )) - goto pages_2; - - if (( rc = golan_alloc_uar(golan) )) - goto teardown; - - if (( rc = golan_create_eq(golan) )) - goto de_uar; - - if (( rc = golan_alloc_pd(golan) )) - goto de_eq; - - if (( rc = golan_create_mkey(golan) )) - goto de_pd; - - golan->flags |= GOLAN_OPEN; - return 0; - - golan_destroy_mkey(golan); -de_pd: - golan_dealloc_pd(golan); -de_eq: - golan_destory_eq(golan); -de_uar: - golan_dealloc_uar(golan); -teardown: - golan_teardown_hca(golan, GOLAN_TEARDOWN_GRACEFUL); -pages_2: -pages_teardown: - golan_handle_pages(golan, GOLAN_INIT_PAGES, GOLAN_PAGES_TAKE); -pages: - golan_handle_pages(golan, GOLAN_BOOT_PAGES, GOLAN_PAGES_TAKE); -disable: - golan_disable_hca(golan); -cmd_uninit: - golan_cmd_uninit(golan); -out: - return rc; -} - -/** - * Close Infiniband link - * - * @v ibdev Infiniband device - */ -static void golan_ib_close ( struct ib_device *ibdev __unused ) {} - -/** - * Initialise Infiniband link - * - * @v ibdev Infiniband device - * @ret rc Return status code - */ -static int golan_ib_open ( struct ib_device *ibdev ) { - DBG ( "%s start\n", __FUNCTION__ ); - - if ( ! ibdev ) - return -EINVAL; - - golan_ib_update ( ibdev ); - - DBG ( "%s end\n", __FUNCTION__ ); - return 0; -} - -/** Golan Infiniband operations */ -static struct ib_device_operations golan_ib_operations = { - .create_cq = golan_create_cq, - .destroy_cq = golan_destroy_cq, - .create_qp = golan_create_qp, - .modify_qp = golan_modify_qp, - .destroy_qp = golan_destroy_qp, - .post_send = golan_post_send, - .post_recv = golan_post_recv, - .poll_cq = golan_poll_cq, - .poll_eq = golan_poll_eq, - .open = golan_ib_open, - .close = golan_ib_close, - .mcast_attach = golan_mcast_attach, - .mcast_detach = golan_mcast_detach, - .set_port_info = golan_inform_sma, - .set_pkey_table = golan_inform_sma, -}; - -static int golan_probe_normal ( struct pci_device *pci ) { - struct golan *golan; - struct ib_device *ibdev; - struct golan_port *port; - int i; - int rc = 0; - - golan = golan_alloc(); - if ( !golan ) { - rc = -ENOMEM; - goto err_golan_alloc; - } - - if ( golan_init_pages( &golan->pages ) ) { - rc = -ENOMEM; - goto err_golan_golan_init_pages; - } - - /* Setup PCI bus and HCA BAR */ - pci_set_drvdata( pci, golan ); - golan->pci = pci; - golan_pci_init( golan ); - /* config command queues */ - if ( fw_ver_and_cmdif( golan ) ) { - rc = -1; - goto err_fw_ver_cmdif; - } - - if ( golan_bring_up( golan ) ) { - DBGC (golan ,"golan bringup failed\n"); - rc = -1; - goto err_golan_bringup; - } - - /* Allocate Infiniband devices */ - for (i = 0; i < golan->caps.num_ports; ++i) { - ibdev = alloc_ibdev( 0 ); - if ( !ibdev ) { - rc = -ENOMEM; - goto err_golan_probe_alloc_ibdev; - } - golan->ports[i].ibdev = ibdev; - golan->ports[i].vep_number = 0; - ibdev->op = &golan_ib_operations; - ibdev->dev = &pci->dev; - ibdev->port = (GOLAN_PORT_BASE + i); - ib_set_drvdata( ibdev, golan ); - } - - /* Register devices */ - for ( i = 0; i < golan->caps.num_ports; ++i ) { - port = &golan->ports[i]; - if ((rc = golan_register_ibdev ( port ) ) != 0 ) - goto err_golan_probe_register_ibdev; - } - - return 0; - - i = golan->caps.num_ports; -err_golan_probe_register_ibdev: - for ( i-- ; ( signed int ) i >= 0 ; i-- ) - unregister_ibdev ( golan->ports[i].ibdev ); - - i = golan->caps.num_ports; -err_golan_probe_alloc_ibdev: - for ( i-- ; ( signed int ) i >= 0 ; i-- ) - ibdev_put ( golan->ports[i].ibdev ); - - golan_bring_down ( golan ); -err_golan_bringup: -err_fw_ver_cmdif: - iounmap( golan->iseg ); - golan_free_pages( &golan->pages ); -err_golan_golan_init_pages: - free ( golan ); -err_golan_alloc: - DBGC (golan ,"%s rc = %d\n", __FUNCTION__, rc); - return rc; -} - -static void golan_remove_normal ( struct pci_device *pci ) { - struct golan *golan = pci_get_drvdata(pci); - struct golan_port *port; - int i; - - DBGC(golan, "%s\n", __FUNCTION__); - - for ( i = ( golan->caps.num_ports - 1 ) ; i >= 0 ; i-- ) { - port = &golan->ports[i]; - unregister_ibdev ( port->ibdev ); - } - for ( i = ( golan->caps.num_ports - 1 ) ; i >= 0 ; i-- ) { - netdev_nullify ( golan->ports[i].netdev ); - netdev_put ( golan->ports[i].netdev ); - } - for ( i = ( golan->caps.num_ports - 1 ) ; i >= 0 ; i-- ) { - ibdev_put ( golan->ports[i].ibdev ); - } - - golan_bring_down(golan); - iounmap( golan->iseg ); - golan_free_pages( &golan->pages ); - free(golan); -} - -/*************************************************************************** - * NODNIC operations - **************************************************************************/ -static mlx_status shomron_fill_eth_send_wqe ( struct ib_device *ibdev, - struct ib_queue_pair *qp, struct ib_address_vector *av __unused, - struct io_buffer *iobuf, struct nodnic_send_wqbb *wqbb, - unsigned long wqe_index ) { - mlx_status status = MLX_SUCCESS; - struct flexboot_nodnic *flexboot_nodnic = ib_get_drvdata ( ibdev ); - struct shomron_nodnic_eth_send_wqe *eth_wqe = NULL; - struct flexboot_nodnic_port *port = &flexboot_nodnic->port[ibdev->port - 1]; - struct flexboot_nodnic_queue_pair *flexboot_nodnic_qp = - ib_qp_get_drvdata ( qp ); - nodnic_qp *nodnic_qp = flexboot_nodnic_qp->nodnic_queue_pair; - struct nodnic_send_ring *send_ring = &nodnic_qp->send; - mlx_uint32 qpn = 0; - - eth_wqe = (struct shomron_nodnic_eth_send_wqe *)wqbb; - memset ( ( ( ( void * ) eth_wqe ) ), 0, - ( sizeof ( *eth_wqe ) ) ); - - status = nodnic_port_get_qpn(&port->port_priv, &send_ring->nodnic_ring, - &qpn); - if ( status != MLX_SUCCESS ) { - DBG("nodnic_port_get_qpn failed\n"); - goto err; - } - -#define SHOMRON_GENERATE_CQE 0x3 -#define SHOMRON_INLINE_HEADERS_SIZE 18 -#define SHOMRON_INLINE_HEADERS_OFFSET 32 - MLX_FILL_2 ( ð_wqe->ctrl, 0, opcode, FLEXBOOT_NODNIC_OPCODE_SEND, - wqe_index, wqe_index & 0xFFFF); - MLX_FILL_2 ( ð_wqe->ctrl, 1, ds, 0x4 , qpn, qpn ); - MLX_FILL_1 ( ð_wqe->ctrl, 2, - ce, SHOMRON_GENERATE_CQE /* generate completion */ - ); - MLX_FILL_2 ( ð_wqe->ctrl, 7, - inline_headers1, - cpu_to_be16(*(mlx_uint16 *)iobuf->data), - inline_headers_size, SHOMRON_INLINE_HEADERS_SIZE - ); - memcpy((void *)ð_wqe->ctrl + SHOMRON_INLINE_HEADERS_OFFSET, - iobuf->data + 2, SHOMRON_INLINE_HEADERS_SIZE - 2); - iob_pull(iobuf, SHOMRON_INLINE_HEADERS_SIZE); - MLX_FILL_1 ( ð_wqe->data[0], 0, - byte_count, iob_len ( iobuf ) ); - MLX_FILL_1 ( ð_wqe->data[0], 1, l_key, - flexboot_nodnic->device_priv.lkey ); - MLX_FILL_H ( ð_wqe->data[0], 2, - local_address_h, virt_to_bus ( iobuf->data ) ); - MLX_FILL_1 ( ð_wqe->data[0], 3, - local_address_l, virt_to_bus ( iobuf->data ) ); -err: - return status; -} - -static mlx_status shomron_fill_completion( void *cqe, struct cqe_data *cqe_data ) { - union shomronprm_completion_entry *cq_entry; - uint32_t opcode; - - cq_entry = (union shomronprm_completion_entry *)cqe; - cqe_data->owner = MLX_GET ( &cq_entry->normal, owner ); - opcode = MLX_GET ( &cq_entry->normal, opcode ); -#define FLEXBOOT_NODNIC_OPCODE_CQ_SEND 0 -#define FLEXBOOT_NODNIC_OPCODE_CQ_RECV 2 -#define FLEXBOOT_NODNIC_OPCODE_CQ_SEND_ERR 13 -#define FLEXBOOT_NODNIC_OPCODE_CQ_RECV_ERR 14 - cqe_data->is_error = - ( opcode >= FLEXBOOT_NODNIC_OPCODE_CQ_RECV_ERR); - if ( cqe_data->is_error ) { - cqe_data->syndrome = MLX_GET ( &cq_entry->error, syndrome ); - cqe_data->vendor_err_syndrome = - MLX_GET ( &cq_entry->error, vendor_error_syndrome ); - cqe_data->is_send = - (opcode == FLEXBOOT_NODNIC_OPCODE_CQ_SEND_ERR); - } else { - cqe_data->is_send = - (opcode == FLEXBOOT_NODNIC_OPCODE_CQ_SEND); - cqe_data->wqe_counter = MLX_GET ( &cq_entry->normal, wqe_counter ); - cqe_data->byte_cnt = MLX_GET ( &cq_entry->normal, byte_cnt ); - - } - if ( cqe_data->is_send == TRUE ) - cqe_data->qpn = MLX_GET ( &cq_entry->normal, qpn ); - else - cqe_data->qpn = MLX_GET ( &cq_entry->normal, srqn ); - - return 0; -} - -static mlx_status shomron_cqe_set_owner ( void *cq, unsigned int num_cqes ) { - unsigned int i = 0; - union shomronprm_completion_entry *cq_list; - - cq_list = (union shomronprm_completion_entry *)cq; - for ( ; i < num_cqes ; i++ ) - MLX_FILL_1 ( &cq_list[i].normal, 15, owner, 1 ); - return 0; -} - -static mlx_size shomron_get_cqe_size () { - return sizeof ( union shomronprm_completion_entry ); -} - -struct flexboot_nodnic_callbacks shomron_nodnic_callbacks = { - .get_cqe_size = shomron_get_cqe_size, - .fill_send_wqe[IB_QPT_ETH] = shomron_fill_eth_send_wqe, - .fill_completion = shomron_fill_completion, - .cqe_set_owner = shomron_cqe_set_owner, - .irq = flexboot_nodnic_eth_irq, -}; - -static int shomron_nodnic_supported = 0; - -static int shomron_nodnic_is_supported ( struct pci_device *pci ) { - if ( pci->device == 0x1011 ) - return 0; - - return flexboot_nodnic_is_supported ( pci ); -} -/**************************************************************************/ - -static int golan_probe ( struct pci_device *pci ) { - int rc = -ENOTSUP; - - DBG ( "%s: start\n", __FUNCTION__ ); - - if ( ! pci ) { - DBG ( "%s: PCI is NULL\n", __FUNCTION__ ); - rc = -EINVAL; - goto probe_done; - } - - shomron_nodnic_supported = shomron_nodnic_is_supported ( pci ); - if ( shomron_nodnic_supported ) { - rc = flexboot_nodnic_probe ( pci, &shomron_nodnic_callbacks, NULL ); - if ( rc == 0 ) { - DBG ( "%s: Using NODNIC driver\n", __FUNCTION__ ); - goto probe_done; - } - shomron_nodnic_supported = 0; - } - - if ( ! shomron_nodnic_supported ) { - DBG ( "%s: Using normal driver\n", __FUNCTION__ ); - rc = golan_probe_normal ( pci ); - } - -probe_done: - DBG ( "%s: rc = %d\n", __FUNCTION__, rc ); - return rc; -} - -static void golan_remove ( struct pci_device *pci ) { - DBG ( "%s: start\n", __FUNCTION__ ); - - if ( ! shomron_nodnic_supported ) { - DBG ( "%s: Using normal driver remove\n", __FUNCTION__ ); - golan_remove_normal ( pci ); - return; - } - - DBG ( "%s: Using NODNIC driver remove\n", __FUNCTION__ ); - - flexboot_nodnic_remove ( pci ); - - DBG ( "%s: end\n", __FUNCTION__ ); -} - -static struct pci_device_id golan_nics[] = { - PCI_ROM ( 0x15b3, 0x1011, "ConnectIB", "ConnectIB HCA driver: DevID 4113", 0 ), - PCI_ROM ( 0x15b3, 0x1013, "ConnectX-4", "ConnectX-4 HCA driver, DevID 4115", 0 ), - PCI_ROM ( 0x15b3, 0x1015, "ConnectX-4Lx", "ConnectX-4Lx HCA driver, DevID 4117", 0 ), -}; - -struct pci_driver golan_driver __pci_driver = { - .ids = golan_nics, - .id_count = (sizeof(golan_nics) / sizeof(golan_nics[0])), - .probe = golan_probe, - .remove = golan_remove, -}; diff --git a/roms/ipxe/src/drivers/infiniband/golan.h b/roms/ipxe/src/drivers/infiniband/golan.h deleted file mode 100755 index a6cb4e744..000000000 --- a/roms/ipxe/src/drivers/infiniband/golan.h +++ /dev/null @@ -1,326 +0,0 @@ -#ifndef _GOLAN_H_ -#define _GOLAN_H_ - -/* - * Copyright (C) 2013-2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <byteswap.h> -#include <errno.h> -#include <stdio.h> -#include <unistd.h> -#include <ipxe/io.h> -#include <ipxe/pci.h> -#include <ipxe/pcibackup.h> -#include "CIB_PRM.h" - -#define GOLAN_PCI_CONFIG_BAR_SIZE 0x100000//HERMON_PCI_CONFIG_BAR_SIZE //TODO: What is the BAR size? - -#define GOLAN_PAS_SIZE sizeof(uint64_t) - -#define GOLAN_INVALID_LKEY 0x00000100UL - -#define GOLAN_MAX_PORTS 2 -#define GOLAN_PORT_BASE 1 - -#define MELLANOX_VID 0x15b3 -#define GOLAN_HCA_BAR PCI_BASE_ADDRESS_0 //BAR 0 - -#define GOLAN_HCR_MAX_WAIT_MS 10000 - -#define min(a,b) ((a)<(b)?(a):(b)) - -#define GOLAN_PAGE_SHIFT 12 -#define GOLAN_PAGE_SIZE (1 << GOLAN_PAGE_SHIFT) -#define GOLAN_PAGE_MASK (GOLAN_PAGE_SIZE - 1) - -#define MAX_MBOX ( GOLAN_PAGE_SIZE / MAILBOX_STRIDE ) -#define DEF_CMD_IDX 1 -#define MEM_CMD_IDX 0 -#define NO_MBOX 0xffff -#define MEM_MBOX MEM_CMD_IDX -#define GEN_MBOX DEF_CMD_IDX - -#define CMD_IF_REV 4 - -#define MAX_PASE_MBOX ((GOLAN_CMD_PAS_CNT) - 2) - -#define CMD_STATUS( golan , idx ) ((struct golan_outbox_hdr *)(get_cmd( (golan) , (idx) )->out))->status -#define CMD_SYND( golan , idx ) ((struct golan_outbox_hdr *)(get_cmd( (golan) , (idx) )->out))->syndrome -#define QRY_PAGES_OUT( golan, idx ) ((struct golan_query_pages_outbox *)(get_cmd( (golan) , (idx) )->out)) - -#define VIRT_2_BE64_BUS( addr ) cpu_to_be64(((unsigned long long )virt_to_bus(addr))) -#define BE64_BUS_2_VIRT( addr ) bus_to_virt(be64_to_cpu(addr)) -#define USR_2_BE64_BUS( addr ) cpu_to_be64(((unsigned long long )user_to_phys(addr, 0))) -#define BE64_BUS_2_USR( addr ) be64_to_cpu(phys_to_user(addr)) - -#define GET_INBOX(golan, idx) (&(((struct mbox *)(golan->mboxes.inbox))[idx])) -#define GET_OUTBOX(golan, idx) (&(((struct mbox *)(golan->mboxes.outbox))[idx])) - -#define GOLAN_MBOX_IN( cmd_ptr, in_ptr ) ( { \ - union { \ - __be32 raw[4]; \ - typeof ( *(in_ptr) ) cooked; \ - } *u = container_of ( &(cmd_ptr)->in[0], typeof ( *u ), raw[0] ); \ - &u->cooked; } ) - -#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) - -/* Fw status fields */ -typedef enum { - NO_ERRORS = 0x0, - SIGNATURE_ERROR = 0x1, - TOKEN_ERROR = 0x2, - BAD_BLOCK_NUMBER = 0x3, - BAD_OUTPUT_POINTER = 0x4, // pointer not align to mailbox size - BAD_INPUT_POINTER = 0x5, // pointer not align to mailbox size - INTERNAL_ERROR = 0x6, - INPUT_LEN_ERROR = 0x7, // input length less than 0x8. - OUTPUT_LEN_ERROR = 0x8, // output length less than 0x8. - RESERVE_NOT_ZERO = 0x9, - BAD_CMD_TYPE = 0x10, -} return_hdr_t; - -struct golan_cmdq_md { - void *addr; - u16 log_stride; - u16 size; -}; - -struct golan_uar { - uint32_t index; - void *virt; - unsigned long phys; -}; - -/* Queue Pair */ -#define GOLAN_SEND_WQE_BB_SIZE 64 -#define GOLAN_SEND_UD_WQE_SIZE sizeof(struct golan_send_wqe_ud) -#define GOLAN_RECV_WQE_SIZE sizeof(struct golan_recv_wqe_ud) -#define GOLAN_WQEBBS_PER_SEND_UD_WQE DIV_ROUND_UP(GOLAN_SEND_UD_WQE_SIZE, GOLAN_SEND_WQE_BB_SIZE) -#define GOLAN_SEND_OPCODE 0x0a -#define GOLAN_WQE_CTRL_WQE_IDX_BIT 8 - -enum golan_ib_qp_state { - GOLAN_IB_QPS_RESET, - GOLAN_IB_QPS_INIT, - GOLAN_IB_QPS_RTR, - GOLAN_IB_QPS_RTS, - GOLAN_IB_QPS_SQD, - GOLAN_IB_QPS_SQE, - GOLAN_IB_QPS_ERR -}; - -struct golan_send_wqe_ud { - struct golan_wqe_ctrl_seg ctrl; - struct golan_av datagram; - struct golan_wqe_data_seg data; -}; - -union golan_send_wqe { - struct golan_send_wqe_ud ud; - uint8_t pad[GOLAN_WQEBBS_PER_SEND_UD_WQE * GOLAN_SEND_WQE_BB_SIZE]; -}; - -struct golan_recv_wqe_ud { - struct golan_wqe_data_seg data[2]; -}; - -struct golan_recv_wq { - struct golan_recv_wqe_ud *wqes; - /* WQ size in bytes */ - int size; - /* In SQ, it will be increased in wqe_size (number of WQEBBs per WQE) */ - u16 next_idx; - /** GRH buffers (if applicable) */ - struct ib_global_route_header *grh; - /** Size of GRH buffers */ - size_t grh_size; -}; - -struct golan_send_wq { - union golan_send_wqe *wqes; - /* WQ size in bytes */ - int size; - /* In SQ, it will be increased in wqe_size (number of WQEBBs per WQE) */ - u16 next_idx; -}; - -struct golan_queue_pair { - void *wqes; - int size; - struct golan_recv_wq rq; - struct golan_send_wq sq; - struct golan_qp_db *doorbell_record; - u32 doorbell_qpn; - enum golan_ib_qp_state state; -}; - -/* Completion Queue */ -#define GOLAN_CQE_OPCODE_NOT_VALID 0x0f -#define GOLAN_CQE_OPCODE_BIT 4 -#define GOLAN_CQ_DB_RECORD_SIZE sizeof(uint64_t) -#define GOLAN_CQE_OWNER_MASK 1 - -#define MANAGE_PAGES_PSA_OFFSET 0 -#define PXE_CMDIF_REF 5 - -enum { - GOLAN_CQE_SW_OWNERSHIP = 0x0, - GOLAN_CQE_HW_OWNERSHIP = 0x1 -}; - -enum { - GOLAN_CQE_SIZE_64 = 0, - GOLAN_CQE_SIZE_128 = 1 -}; - -struct golan_completion_queue { - struct golan_cqe64 *cqes; - int size; - __be64 *doorbell_record; -}; - - -/* Event Queue */ -#define GOLAN_EQE_SIZE sizeof(struct golan_eqe) -#define GOLAN_NUM_EQES 8 -#define GOLAN_EQ_DOORBELL_OFFSET 0x40 - -#define GOLAN_EQ_MAP_ALL_EVENTS \ - ((1 << GOLAN_EVENT_TYPE_PATH_MIG )| \ - (1 << GOLAN_EVENT_TYPE_COMM_EST )| \ - (1 << GOLAN_EVENT_TYPE_SQ_DRAINED )| \ - (1 << GOLAN_EVENT_TYPE_SRQ_LAST_WQE )| \ - (1 << GOLAN_EVENT_TYPE_SRQ_RQ_LIMIT )| \ - (1 << GOLAN_EVENT_TYPE_CQ_ERROR )| \ - (1 << GOLAN_EVENT_TYPE_WQ_CATAS_ERROR )| \ - (1 << GOLAN_EVENT_TYPE_PATH_MIG_FAILED )| \ - (1 << GOLAN_EVENT_TYPE_WQ_INVAL_REQ_ERROR )| \ - (1 << GOLAN_EVENT_TYPE_WQ_ACCESS_ERROR )| \ - (1 << GOLAN_EVENT_TYPE_SRQ_CATAS_ERROR )| \ - (1 << GOLAN_EVENT_TYPE_INTERNAL_ERROR )| \ - (1 << GOLAN_EVENT_TYPE_PORT_CHANGE )| \ - (1 << GOLAN_EVENT_TYPE_GPIO_EVENT )| \ - (1 << GOLAN_EVENT_TYPE_CLIENT_RE_REGISTER )| \ - (1 << GOLAN_EVENT_TYPE_REMOTE_CONFIG )| \ - (1 << GOLAN_EVENT_TYPE_DB_BF_CONGESTION )| \ - (1 << GOLAN_EVENT_TYPE_STALL_EVENT )| \ - (1 << GOLAN_EVENT_TYPE_PACKET_DROPPED )| \ - (1 << GOLAN_EVENT_TYPE_CMD )| \ - (1 << GOLAN_EVENT_TYPE_PAGE_REQUEST )) - -enum golan_event { - GOLAN_EVENT_TYPE_COMP = 0x0, - - GOLAN_EVENT_TYPE_PATH_MIG = 0x01, - GOLAN_EVENT_TYPE_COMM_EST = 0x02, - GOLAN_EVENT_TYPE_SQ_DRAINED = 0x03, - GOLAN_EVENT_TYPE_SRQ_LAST_WQE = 0x13, - GOLAN_EVENT_TYPE_SRQ_RQ_LIMIT = 0x14, - - GOLAN_EVENT_TYPE_CQ_ERROR = 0x04, - GOLAN_EVENT_TYPE_WQ_CATAS_ERROR = 0x05, - GOLAN_EVENT_TYPE_PATH_MIG_FAILED = 0x07, - GOLAN_EVENT_TYPE_WQ_INVAL_REQ_ERROR = 0x10, - GOLAN_EVENT_TYPE_WQ_ACCESS_ERROR = 0x11, - GOLAN_EVENT_TYPE_SRQ_CATAS_ERROR = 0x12, - - GOLAN_EVENT_TYPE_INTERNAL_ERROR = 0x08, - GOLAN_EVENT_TYPE_PORT_CHANGE = 0x09, - GOLAN_EVENT_TYPE_GPIO_EVENT = 0x15, -// GOLAN_EVENT_TYPE_CLIENT_RE_REGISTER = 0x16, - GOLAN_EVENT_TYPE_REMOTE_CONFIG = 0x19, - - GOLAN_EVENT_TYPE_DB_BF_CONGESTION = 0x1a, - GOLAN_EVENT_TYPE_STALL_EVENT = 0x1b, - - GOLAN_EVENT_TYPE_PACKET_DROPPED = 0x1f, - - GOLAN_EVENT_TYPE_CMD = 0x0a, - GOLAN_EVENT_TYPE_PAGE_REQUEST = 0x0b, - GOLAN_EVENT_TYPE_PAGE_FAULT = 0x0C, -}; - -enum golan_port_sub_event { - GOLAN_PORT_CHANGE_SUBTYPE_DOWN = 1, - GOLAN_PORT_CHANGE_SUBTYPE_ACTIVE = 4, - GOLAN_PORT_CHANGE_SUBTYPE_INITIALIZED = 5, - GOLAN_PORT_CHANGE_SUBTYPE_LID = 6, - GOLAN_PORT_CHANGE_SUBTYPE_PKEY = 7, - GOLAN_PORT_CHANGE_SUBTYPE_GUID = 8, - GOLAN_PORT_CHANGE_SUBTYPE_CLIENT_REREG = 9 -}; - - -enum { - GOLAN_EQE_SW_OWNERSHIP = 0x0, - GOLAN_EQE_HW_OWNERSHIP = 0x1 -}; - -enum { - GOLAN_EQ_UNARMED = 0, - GOLAN_EQ_ARMED = 1, -}; - -struct golan_event_queue { - uint8_t eqn; - uint64_t mask; - struct golan_eqe *eqes; - int size; - __be32 *doorbell; - uint32_t cons_index; -}; - -struct golan_port { - /** Infiniband device */ - struct ib_device *ibdev; - /** Network device */ - struct net_device *netdev; - /** VEP number */ - u8 vep_number; -}; - -struct golan_mboxes { - void *inbox; - void *outbox; -}; - -#define GOLAN_OPEN 0x1 - -struct golan { - struct pci_device *pci; - struct golan_hca_init_seg *iseg; - struct golan_cmdq_md cmd; - struct golan_hca_cap caps; /* stored as big indian*/ - struct golan_mboxes mboxes; - struct list_head pages; - uint32_t cmd_bm; - uint32_t total_dma_pages; - struct golan_uar uar; - struct golan_event_queue eq; - uint32_t pdn; - u32 mkey; - u32 flags; - - struct golan_port ports[GOLAN_MAX_PORTS]; -}; - -#endif /* _GOLAN_H_*/ diff --git a/roms/ipxe/src/drivers/infiniband/hermon.c b/roms/ipxe/src/drivers/infiniband/hermon.c index 79d606093..a9c728706 100644 --- a/roms/ipxe/src/drivers/infiniband/hermon.c +++ b/roms/ipxe/src/drivers/infiniband/hermon.c @@ -1111,8 +1111,6 @@ static int hermon_create_qp ( struct ib_device *ibdev, struct hermon *hermon = ib_get_drvdata ( ibdev ); struct hermon_queue_pair *hermon_qp; struct hermonprm_qp_ee_state_transitions qpctx; - struct hermonprm_wqe_segment_data_ptr *data; - unsigned int i; int rc; /* Calculate queue pair number */ @@ -1149,14 +1147,8 @@ static int hermon_create_qp ( struct ib_device *ibdev, sizeof ( hermon_qp->send.wqe[0] ) ); hermon_qp->recv.wqe_size = ( qp->recv.num_wqes * sizeof ( hermon_qp->recv.wqe[0] ) ); - if ( ( qp->type == IB_QPT_SMI ) || ( qp->type == IB_QPT_GSI ) || - ( qp->type == IB_QPT_UD ) ) { - hermon_qp->recv.grh_size = ( qp->recv.num_wqes * - sizeof ( hermon_qp->recv.grh[0] )); - } hermon_qp->wqe_size = ( hermon_qp->send.wqe_size + - hermon_qp->recv.wqe_size + - hermon_qp->recv.grh_size ); + hermon_qp->recv.wqe_size ); hermon_qp->wqe = malloc_dma ( hermon_qp->wqe_size, sizeof ( hermon_qp->send.wqe[0] ) ); if ( ! hermon_qp->wqe ) { @@ -1164,21 +1156,9 @@ static int hermon_create_qp ( struct ib_device *ibdev, goto err_alloc_wqe; } hermon_qp->send.wqe = hermon_qp->wqe; - hermon_qp->recv.wqe = ( hermon_qp->wqe + hermon_qp->send.wqe_size ); - if ( hermon_qp->recv.grh_size ) { - hermon_qp->recv.grh = ( hermon_qp->wqe + - hermon_qp->send.wqe_size + - hermon_qp->recv.wqe_size ); - } - - /* Initialise work queue entries */ memset ( hermon_qp->send.wqe, 0xff, hermon_qp->send.wqe_size ); + hermon_qp->recv.wqe = ( hermon_qp->wqe + hermon_qp->send.wqe_size ); memset ( hermon_qp->recv.wqe, 0, hermon_qp->recv.wqe_size ); - data = &hermon_qp->recv.wqe[0].recv.data[0]; - for ( i = 0 ; i < ( hermon_qp->recv.wqe_size / sizeof ( *data ) ); i++){ - MLX_FILL_1 ( data, 1, l_key, HERMON_INVALID_LKEY ); - data++; - } /* Allocate MTT entries */ if ( ( rc = hermon_alloc_mtt ( hermon, hermon_qp->wqe, @@ -1653,8 +1633,6 @@ static int hermon_post_recv ( struct ib_device *ibdev, struct ib_work_queue *wq = &qp->recv; struct hermon_recv_work_queue *hermon_recv_wq = &hermon_qp->recv; struct hermonprm_recv_wqe *wqe; - struct hermonprm_wqe_segment_data_ptr *data; - struct ib_global_route_header *grh; unsigned int wqe_idx_mask; /* Allocate work queue entry */ @@ -1668,19 +1646,12 @@ static int hermon_post_recv ( struct ib_device *ibdev, wqe = &hermon_recv_wq->wqe[wq->next_idx & wqe_idx_mask].recv; /* Construct work queue entry */ - data = &wqe->data[0]; - if ( hermon_qp->recv.grh ) { - grh = &hermon_qp->recv.grh[wq->next_idx & wqe_idx_mask]; - MLX_FILL_1 ( data, 0, byte_count, sizeof ( *grh ) ); - MLX_FILL_1 ( data, 1, l_key, hermon->lkey ); - MLX_FILL_H ( data, 2, local_address_h, virt_to_bus ( grh ) ); - MLX_FILL_1 ( data, 3, local_address_l, virt_to_bus ( grh ) ); - data++; - } - MLX_FILL_1 ( data, 0, byte_count, iob_tailroom ( iobuf ) ); - MLX_FILL_1 ( data, 1, l_key, hermon->lkey ); - MLX_FILL_H ( data, 2, local_address_h, virt_to_bus ( iobuf->data ) ); - MLX_FILL_1 ( data, 3, local_address_l, virt_to_bus ( iobuf->data ) ); + MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_tailroom ( iobuf ) ); + MLX_FILL_1 ( &wqe->data[0], 1, l_key, hermon->lkey ); + MLX_FILL_H ( &wqe->data[0], 2, + local_address_h, virt_to_bus ( iobuf->data ) ); + MLX_FILL_1 ( &wqe->data[0], 3, + local_address_l, virt_to_bus ( iobuf->data ) ); /* Update work queue's index */ wq->next_idx++; @@ -1705,7 +1676,6 @@ static int hermon_complete ( struct ib_device *ibdev, struct ib_completion_queue *cq, union hermonprm_completion_entry *cqe ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); - struct hermon_queue_pair *hermon_qp; struct ib_work_queue *wq; struct ib_queue_pair *qp; struct io_buffer *iobuf; @@ -1743,7 +1713,6 @@ static int hermon_complete ( struct ib_device *ibdev, return -EIO; } qp = wq->qp; - hermon_qp = ib_qp_get_drvdata ( qp ); /* Identify work queue entry */ wqe_idx = MLX_GET ( &cqe->normal, wqe_counter ); @@ -1769,6 +1738,8 @@ static int hermon_complete ( struct ib_device *ibdev, } else { /* Set received length */ len = MLX_GET ( &cqe->normal, byte_cnt ); + assert ( len <= iob_tailroom ( iobuf ) ); + iob_put ( iobuf, len ); memset ( &recv_dest, 0, sizeof ( recv_dest ) ); recv_dest.qpn = qpn; memset ( &recv_source, 0, sizeof ( recv_source ) ); @@ -1776,10 +1747,9 @@ static int hermon_complete ( struct ib_device *ibdev, case IB_QPT_SMI: case IB_QPT_GSI: case IB_QPT_UD: - /* Locate corresponding GRH */ - assert ( hermon_qp->recv.grh != NULL ); - grh = &hermon_qp->recv.grh[ wqe_idx & wqe_idx_mask ]; - len -= sizeof ( *grh ); + assert ( iob_len ( iobuf ) >= sizeof ( *grh ) ); + grh = iobuf->data; + iob_pull ( iobuf, sizeof ( *grh ) ); /* Construct address vector */ source = &recv_source; source->qpn = MLX_GET ( &cqe->normal, srq_rqpn ); @@ -1805,8 +1775,6 @@ static int hermon_complete ( struct ib_device *ibdev, assert ( 0 ); return -EINVAL; } - assert ( len <= iob_tailroom ( iobuf ) ); - iob_put ( iobuf, len ); /* Hand off to completion handler */ ib_complete_recv ( ibdev, qp, &recv_dest, source, iobuf, rc ); } @@ -3274,7 +3242,7 @@ static int hermon_eth_open ( struct net_device *netdev ) { port->eth_qp = ib_create_qp ( ibdev, IB_QPT_ETH, HERMON_ETH_NUM_SEND_WQES, port->eth_cq, HERMON_ETH_NUM_RECV_WQES, port->eth_cq, - &hermon_eth_qp_op, netdev->name ); + &hermon_eth_qp_op ); if ( ! port->eth_qp ) { DBGC ( hermon, "Hermon %p port %d could not create queue " "pair\n", hermon, ibdev->port ); @@ -3780,6 +3748,24 @@ static void hermon_free ( struct hermon *hermon ) { } /** + * Initialise Hermon PCI parameters + * + * @v hermon Hermon device + */ +static void hermon_pci_init ( struct hermon *hermon ) { + struct pci_device *pci = hermon->pci; + + /* Fix up PCI device */ + adjust_pci_device ( pci ); + + /* Get PCI BARs */ + hermon->config = ioremap ( pci_bar_start ( pci, HERMON_PCI_CONFIG_BAR), + HERMON_PCI_CONFIG_BAR_SIZE ); + hermon->uar = ioremap ( pci_bar_start ( pci, HERMON_PCI_UAR_BAR ), + HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE ); +} + +/** * Probe PCI device * * @v pci PCI device @@ -3803,14 +3789,8 @@ static int hermon_probe ( struct pci_device *pci ) { pci_set_drvdata ( pci, hermon ); hermon->pci = pci; - /* Fix up PCI device */ - adjust_pci_device ( pci ); - - /* Map PCI BARs */ - hermon->config = ioremap ( pci_bar_start ( pci, HERMON_PCI_CONFIG_BAR ), - HERMON_PCI_CONFIG_BAR_SIZE ); - hermon->uar = ioremap ( pci_bar_start ( pci, HERMON_PCI_UAR_BAR ), - HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE ); + /* Initialise PCI parameters */ + hermon_pci_init ( hermon ); /* Reset device */ hermon_reset ( hermon ); @@ -3905,8 +3885,6 @@ static int hermon_probe ( struct pci_device *pci ) { err_get_cap: hermon_stop_firmware ( hermon ); err_start_firmware: - iounmap ( hermon->uar ); - iounmap ( hermon->config ); hermon_free ( hermon ); err_alloc: return rc; @@ -3932,8 +3910,6 @@ static void hermon_remove ( struct pci_device *pci ) { } for ( i = ( hermon->cap.num_ports - 1 ) ; i >= 0 ; i-- ) ibdev_put ( hermon->port[i].ibdev ); - iounmap ( hermon->uar ); - iounmap ( hermon->config ); hermon_free ( hermon ); } @@ -3957,12 +3933,8 @@ static int hermon_bofm_probe ( struct pci_device *pci ) { pci_set_drvdata ( pci, hermon ); hermon->pci = pci; - /* Fix up PCI device */ - adjust_pci_device ( pci ); - - /* Map PCI BAR */ - hermon->config = ioremap ( pci_bar_start ( pci, HERMON_PCI_CONFIG_BAR ), - HERMON_PCI_CONFIG_BAR_SIZE ); + /* Initialise PCI parameters */ + hermon_pci_init ( hermon ); /* Initialise BOFM device */ bofm_init ( &hermon->bofm, pci, &hermon_bofm_operations ); @@ -3977,7 +3949,6 @@ static int hermon_bofm_probe ( struct pci_device *pci ) { return 0; err_bofm_register: - iounmap ( hermon->config ); hermon_free ( hermon ); err_alloc: return rc; @@ -3992,7 +3963,6 @@ static void hermon_bofm_remove ( struct pci_device *pci ) { struct hermon *hermon = pci_get_drvdata ( pci ); bofm_unregister ( &hermon->bofm ); - iounmap ( hermon->config ); hermon_free ( hermon ); } diff --git a/roms/ipxe/src/drivers/infiniband/hermon.h b/roms/ipxe/src/drivers/infiniband/hermon.h index 61e285781..e0b028f26 100644 --- a/roms/ipxe/src/drivers/infiniband/hermon.h +++ b/roms/ipxe/src/drivers/infiniband/hermon.h @@ -515,7 +515,7 @@ struct hermonprm_eth_send_wqe { struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_GATHER]; } __attribute__ (( packed )); -#define HERMON_MAX_SCATTER 2 +#define HERMON_MAX_SCATTER 1 struct hermonprm_recv_wqe { struct hermonprm_wqe_segment_data_ptr data[HERMON_MAX_SCATTER]; @@ -686,10 +686,6 @@ struct hermon_recv_work_queue { union hermon_recv_wqe *wqe; /** Size of work queue */ size_t wqe_size; - /** GRH buffers (if applicable) */ - struct ib_global_route_header *grh; - /** Size of GRH buffers */ - size_t grh_size; /** Doorbell record */ struct hermonprm_qp_db_record *doorbell; }; diff --git a/roms/ipxe/src/drivers/infiniband/linda.c b/roms/ipxe/src/drivers/infiniband/linda.c index 77d50d110..a6ae9f529 100644 --- a/roms/ipxe/src/drivers/infiniband/linda.c +++ b/roms/ipxe/src/drivers/infiniband/linda.c @@ -112,21 +112,32 @@ struct linda { * This card requires atomic 64-bit accesses. Strange things happen * if you try to use 32-bit accesses; sometimes they work, sometimes * they don't, sometimes you get random data. + * + * These accessors use the "movq" MMX instruction, and so won't work + * on really old Pentiums (which won't have PCIe anyway, so this is + * something of a moot point). */ /** * Read Linda qword register * * @v linda Linda device - * @v qword Register buffer to read into + * @v dwords Register buffer to read into * @v offset Register offset */ -static void linda_readq ( struct linda *linda, uint64_t *qword, +static void linda_readq ( struct linda *linda, uint32_t *dwords, unsigned long offset ) { - *qword = readq ( linda->regs + offset ); + void *addr = ( linda->regs + offset ); + + __asm__ __volatile__ ( "movq (%1), %%mm0\n\t" + "movq %%mm0, (%0)\n\t" + : : "r" ( dwords ), "r" ( addr ) : "memory" ); + + DBGIO ( "[%08lx] => %08x%08x\n", + virt_to_phys ( addr ), dwords[1], dwords[0] ); } #define linda_readq( _linda, _ptr, _offset ) \ - linda_readq ( (_linda), (_ptr)->u.qwords, (_offset) ) + linda_readq ( (_linda), (_ptr)->u.dwords, (_offset) ) #define linda_readq_array8b( _linda, _ptr, _offset, _idx ) \ linda_readq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) ) #define linda_readq_array64k( _linda, _ptr, _offset, _idx ) \ @@ -136,15 +147,22 @@ static void linda_readq ( struct linda *linda, uint64_t *qword, * Write Linda qword register * * @v linda Linda device - * @v qword Register buffer to write + * @v dwords Register buffer to write * @v offset Register offset */ -static void linda_writeq ( struct linda *linda, const uint64_t *qword, +static void linda_writeq ( struct linda *linda, const uint32_t *dwords, unsigned long offset ) { - writeq ( *qword, ( linda->regs + offset ) ); + void *addr = ( linda->regs + offset ); + + DBGIO ( "[%08lx] <= %08x%08x\n", + virt_to_phys ( addr ), dwords[1], dwords[0] ); + + __asm__ __volatile__ ( "movq (%0), %%mm0\n\t" + "movq %%mm0, (%1)\n\t" + : : "r" ( dwords ), "r" ( addr ) : "memory" ); } #define linda_writeq( _linda, _ptr, _offset ) \ - linda_writeq ( (_linda), (_ptr)->u.qwords, (_offset) ) + linda_writeq ( (_linda), (_ptr)->u.dwords, (_offset) ) #define linda_writeq_array8b( _linda, _ptr, _offset, _idx ) \ linda_writeq ( (_linda), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) ) #define linda_writeq_array64k( _linda, _ptr, _offset, _idx ) \ @@ -1271,15 +1289,8 @@ static void linda_complete_recv ( struct ib_device *ibdev, /* Completing the eager buffer described in * this header entry. */ - if ( payload_len <= iob_tailroom ( iobuf ) ) { - iob_put ( iobuf, payload_len ); - rc = ( err ? - -EIO : ( useegrbfr ? 0 : -ECANCELED ) ); - } else { - DBGC ( linda, "Linda %p bad payload len %zd\n", - linda, payload_len ); - rc = -EPROTO; - } + iob_put ( iobuf, payload_len ); + rc = ( err ? -EIO : ( useegrbfr ? 0 : -ECANCELED ) ); /* Redirect to target QP if necessary */ if ( qp != intended_qp ) { DBGC ( linda, "Linda %p redirecting QPN %ld " @@ -1290,7 +1301,7 @@ static void linda_complete_recv ( struct ib_device *ibdev, intended_qp->recv.fill++; } ib_complete_recv ( ibdev, intended_qp, &dest, &source, - iobuf, rc ); + iobuf, rc); } else { /* Completing on a skipped-over eager buffer */ ib_complete_recv ( ibdev, qp, &dest, &source, iobuf, @@ -2334,7 +2345,7 @@ static int linda_probe ( struct pci_device *pci ) { /* Fix up PCI device */ adjust_pci_device ( pci ); - /* Map PCI BARs */ + /* Get PCI BARs */ linda->regs = ioremap ( pci->membase, LINDA_BAR0_SIZE ); DBGC2 ( linda, "Linda %p has BAR at %08lx\n", linda, pci->membase ); @@ -2395,7 +2406,6 @@ static int linda_probe ( struct pci_device *pci ) { err_init_ib_serdes: err_read_eeprom: err_init_i2c: - iounmap ( linda->regs ); ibdev_put ( ibdev ); err_alloc_ibdev: return rc; @@ -2413,7 +2423,6 @@ static void linda_remove ( struct pci_device *pci ) { unregister_ibdev ( ibdev ); linda_fini_recv ( linda ); linda_fini_send ( linda ); - iounmap ( linda->regs ); ibdev_put ( ibdev ); } diff --git a/roms/ipxe/src/drivers/infiniband/linda.h b/roms/ipxe/src/drivers/infiniband/linda.h index 44c7686f4..46a920a17 100644 --- a/roms/ipxe/src/drivers/infiniband/linda.h +++ b/roms/ipxe/src/drivers/infiniband/linda.h @@ -33,8 +33,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * */ -#define PSEUDOBIT_LITTLE_ENDIAN -#include <ipxe/pseudobit.h> +#define BITOPS_LITTLE_ENDIAN +#include <ipxe/bitops.h> #include "qib_7220_regs.h" struct ib_device; diff --git a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_cmd.h b/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_cmd.h deleted file mode 100644 index e1e89b4c3..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_cmd.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef NODNIC_CMD_H_ -#define NODNIC_CMD_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_nodnic_data_structures.h" -#include "../../mlx_utils/include/public/mlx_utils.h" -#include "../../mlx_utils/include/public/mlx_pci_gw.h" - -mlx_status -nodnic_cmd_read( - IN nodnic_device_priv *device_priv, - IN mlx_uint32 address, - OUT mlx_pci_gw_buffer *buffer - ); - -mlx_status -nodnic_cmd_write( - IN nodnic_device_priv *device_priv, - IN mlx_uint32 address, - IN mlx_pci_gw_buffer buffer - ); - -#endif /* STUB_NODNIC_CMD_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_device.h b/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_device.h deleted file mode 100644 index b0cc7f723..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_device.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef NODNIC_DEVICE_H_ -#define NODNIC_DEVICE_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_nodnic_data_structures.h" - -#define NODIC_SUPPORTED_REVISION 1 -//Initialization segment -#define NODNIC_CMDQ_PHY_ADDR_HIGH_OFFSET 0x10 -#define NODNIC_CMDQ_PHY_ADDR_LOW_OFFSET 0x14 -#define NODNIC_NIC_INTERFACE_OFFSET 0x14 -#define NODNIC_INITIALIZING_OFFSET 0x1fc -#define NODNIC_NIC_INTERFACE_SUPPORTED_OFFSET 0x1fc -#define NODNIC_LOCATION_OFFSET 0x240 - -#define NODNIC_CMDQ_PHY_ADDR_LOW_MASK 0xFFFFE000 -#define NODNIC_NIC_INTERFACE_SUPPORTED_MASK 0x4000000 - -#define NODNIC_NIC_INTERFACE_BIT 9 -#define NODNIC_DISABLE_INTERFACE_BIT 8 -#define NODNIC_NIC_INTERFACE_SUPPORTED_BIT 26 -#define NODNIC_INITIALIZING_BIT 31 - -#define NODNIC_NIC_DISABLE_INT_OFFSET 0x100c - -//nodnic segment -#define NODNIC_REVISION_OFFSET 0x0 -#define NODNIC_HARDWARE_FORMAT_OFFSET 0x0 - - - -mlx_status -nodnic_device_init( - IN nodnic_device_priv *device_priv - ); - -mlx_status -nodnic_device_teardown( - IN nodnic_device_priv *device_priv - ); - - -mlx_status -nodnic_device_get_cap( - IN nodnic_device_priv *device_priv - ); - -mlx_status -nodnic_device_clear_int ( - IN nodnic_device_priv *device_priv - ); - -mlx_status -nodnic_device_get_fw_version( - IN nodnic_device_priv *device_priv, - OUT mlx_uint16 *fw_ver_minor, - OUT mlx_uint16 *fw_ver_sub_minor, - OUT mlx_uint16 *fw_ver_major - ); -#endif /* STUB_NODNIC_DEVICE_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_nodnic_data_structures.h b/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_nodnic_data_structures.h deleted file mode 100644 index f58213b98..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_nodnic_data_structures.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef NODNIC_NODNICDATASTRUCTURES_H_ -#define NODNIC_NODNICDATASTRUCTURES_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../mlx_utils/include/public/mlx_utils.h" - -/* todo: fix coding convention */ -#define NODNIC_MEMORY_ALIGN 0x1000 - -#define NODNIC_MAX_MAC_FILTERS 5 -#define NODNIC_MAX_MGID_FILTERS 4 - -typedef struct _nodnic_device_priv nodnic_device_priv; -typedef struct _nodnic_port_priv nodnic_port_priv; -typedef struct _nodnic_device_capabilites nodnic_device_capabilites; -typedef struct _nodnic_qp nodnic_qp; -typedef struct _nodnic_cq nodnic_cq; -typedef struct _nodnic_eq nodnic_eq; - -/* NODNIC Port states - * Bit 0 - port open/close - * Bit 1 - port is [not] in disabling DMA - * 0 - closed and not disabling DMA - * 1 - opened and not disabling DMA - * 3 - opened and disabling DMA - */ -#define NODNIC_PORT_OPENED 0b00000001 -#define NODNIC_PORT_DISABLING_DMA 0b00000010 - -typedef enum { - ConnectX3 = 0, - Connectx4 -}nodnic_hardware_format; - - -typedef enum { - NODNIC_QPT_SMI, - NODNIC_QPT_GSI, - NODNIC_QPT_UD, - NODNIC_QPT_RC, - NODNIC_QPT_ETH, -}nodnic_queue_pair_type; -typedef enum { - NODNIC_PORT_TYPE_IB = 0, - NODNIC_PORT_TYPE_ETH, - NODNIC_PORT_TYPE_UNKNOWN, -}nodnic_port_type; - - -#define RECV_WQE_SIZE 16 -#define NODNIC_WQBB_SIZE 64 -/** A nodnic send wqbb */ -struct nodnic_send_wqbb { - mlx_uint8 force_align[NODNIC_WQBB_SIZE]; -}; -struct nodnic_ring { - mlx_uint32 offset; - /** Work queue entries */ - /* TODO: add to memory entity */ - mlx_physical_address wqe_physical; - mlx_void *map; - /** Size of work queue */ - mlx_size wq_size; - /** Next work queue entry index - * - * This is the index of the next entry to be filled (i.e. the - * first empty entry). This value is not bounded by num_wqes; - * users must logical-AND with (num_wqes-1) to generate an - * array index. - */ - mlx_uint32 num_wqes; - mlx_uint32 qpn; - mlx_uint32 next_idx; - mlx_uint32 ring_pi; -}; - -struct nodnic_send_ring{ - struct nodnic_ring nodnic_ring; - struct nodnic_send_wqbb *wqe_virt; -}; - - -struct nodnic_recv_ring{ - struct nodnic_ring nodnic_ring; - void *wqe_virt; -}; -struct _nodnic_qp{ - nodnic_queue_pair_type type; - struct nodnic_send_ring send; - struct nodnic_recv_ring receive; -}; - -struct _nodnic_cq{ - /** cq entries */ - mlx_void *cq_virt; - mlx_physical_address cq_physical; - mlx_void *map; - /** cq */ - mlx_size cq_size; -}; - -struct _nodnic_eq{ - mlx_void *eq_virt; - mlx_physical_address eq_physical; - mlx_void *map; - mlx_size eq_size; -}; -struct _nodnic_device_capabilites{ - mlx_boolean support_mac_filters; - mlx_boolean support_promisc_filter; - mlx_boolean support_promisc_multicast_filter; - mlx_uint8 log_working_buffer_size; - mlx_uint8 log_pkey_table_size; - mlx_boolean num_ports; // 0 - single port, 1 - dual port - mlx_uint8 log_max_ring_size; -#ifdef DEVICE_CX3 - mlx_uint8 crspace_doorbells; -#endif -}; - -#ifdef DEVICE_CX3 -/* This is the structure of the data in the scratchpad - * Read/Write data from/to its field using PCI accesses only */ -typedef struct _nodnic_port_data_flow_gw nodnic_port_data_flow_gw; -struct _nodnic_port_data_flow_gw { - mlx_uint32 send_doorbell; - mlx_uint32 recv_doorbell; - mlx_uint32 reserved2[2]; - mlx_uint32 armcq_cq_ci_dword; - mlx_uint32 dma_en; -} __attribute__ ((packed)); -#endif - -struct _nodnic_device_priv{ - mlx_boolean is_initiailzied; - mlx_utils *utils; - - //nodnic structure offset in init segment - mlx_uint32 device_offset; - - nodnic_device_capabilites device_cap; - - mlx_uint8 nodnic_revision; - nodnic_hardware_format hardware_format; - mlx_uint32 pd; - mlx_uint32 lkey; - mlx_uint64 device_guid; - nodnic_port_priv *ports; -#ifdef DEVICE_CX3 - mlx_void *crspace_clear_int; -#endif -}; - -struct _nodnic_port_priv{ - nodnic_device_priv *device; - mlx_uint32 port_offset; - mlx_uint8 port_state; - mlx_boolean network_state; - mlx_boolean dma_state; - nodnic_port_type port_type; - mlx_uint8 port_num; - nodnic_eq eq; - mlx_mac_address mac_filters[5]; - mlx_status (*send_doorbell)( - IN nodnic_port_priv *port_priv, - IN struct nodnic_ring *ring, - IN mlx_uint16 index); - mlx_status (*recv_doorbell)( - IN nodnic_port_priv *port_priv, - IN struct nodnic_ring *ring, - IN mlx_uint16 index); - mlx_status (*set_dma)( - IN nodnic_port_priv *port_priv, - IN mlx_boolean value); -#ifdef DEVICE_CX3 - nodnic_port_data_flow_gw *data_flow_gw; -#endif -}; - - -#endif /* STUB_NODNIC_NODNICDATASTRUCTURES_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_port.h b/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_port.h deleted file mode 100644 index 4fd96a6da..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/include/mlx_port.h +++ /dev/null @@ -1,229 +0,0 @@ -#ifndef NODNIC_PORT_H_ -#define NODNIC_PORT_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_nodnic_data_structures.h" - -#define NODNIC_PORT_MAC_FILTERS_OFFSET 0x10 - -typedef enum { - nodnic_port_option_link_type = 0, - nodnic_port_option_mac_low, - nodnic_port_option_mac_high, - nodnic_port_option_log_cq_size, - nodnic_port_option_reset_needed, - nodnic_port_option_mac_filters_en, - nodnic_port_option_port_state, - nodnic_port_option_network_en, - nodnic_port_option_dma_en, - nodnic_port_option_eq_addr_low, - nodnic_port_option_eq_addr_high, - nodnic_port_option_cq_addr_low, - nodnic_port_option_cq_addr_high, - nodnic_port_option_port_management_change_event, - nodnic_port_option_port_promisc_en, - nodnic_port_option_arm_cq, - nodnic_port_option_port_promisc_multicast_en, -#ifdef DEVICE_CX3 - nodnic_port_option_crspace_en, -#endif -}nodnic_port_option; - -struct nodnic_port_data_entry{ - nodnic_port_option option; - mlx_uint32 offset; - mlx_uint8 align; - mlx_uint32 mask; -}; - -struct nodnic_qp_data_entry{ - nodnic_queue_pair_type type; - mlx_uint32 send_offset; - mlx_uint32 recv_offset; -}; - - -typedef enum { - nodnic_port_state_down = 0, - nodnic_port_state_initialize, - nodnic_port_state_armed, - nodnic_port_state_active, -}nodnic_port_state; - -mlx_status -nodnic_port_get_state( - IN nodnic_port_priv *port_priv, - OUT nodnic_port_state *state - ); - -mlx_status -nodnic_port_get_type( - IN nodnic_port_priv *port_priv, - OUT nodnic_port_type *type - ); - -mlx_status -nodnic_port_query( - IN nodnic_port_priv *port_priv, - IN nodnic_port_option option, - OUT mlx_uint32 *out - ); - -mlx_status -nodnic_port_set( - IN nodnic_port_priv *port_priv, - IN nodnic_port_option option, - IN mlx_uint32 in - ); - -mlx_status -nodnic_port_create_cq( - IN nodnic_port_priv *port_priv, - IN mlx_size cq_size, - OUT nodnic_cq **cq - ); - -mlx_status -nodnic_port_destroy_cq( - IN nodnic_port_priv *port_priv, - IN nodnic_cq *cq - ); - -mlx_status -nodnic_port_create_qp( - IN nodnic_port_priv *port_priv, - IN nodnic_queue_pair_type type, - IN mlx_size send_wq_size, - IN mlx_uint32 send_wqe_num, - IN mlx_size receive_wq_size, - IN mlx_uint32 recv_wqe_num, - OUT nodnic_qp **qp - ); - -mlx_status -nodnic_port_destroy_qp( - IN nodnic_port_priv *port_priv, - IN nodnic_queue_pair_type type, - IN nodnic_qp *qp - ); -mlx_status -nodnic_port_get_qpn( - IN nodnic_port_priv *port_priv, - IN struct nodnic_ring *ring, - OUT mlx_uint32 *qpn - ); -mlx_status -nodnic_port_update_ring_doorbell( - IN nodnic_port_priv *port_priv, - IN struct nodnic_ring *ring, - IN mlx_uint16 index - ); -mlx_status -nodnic_port_get_cq_size( - IN nodnic_port_priv *port_priv, - OUT mlx_uint64 *cq_size - ); - -mlx_status -nodnic_port_allocate_eq( - IN nodnic_port_priv *port_priv, - IN mlx_uint8 log_eq_size - ); -mlx_status -nodnic_port_free_eq( - IN nodnic_port_priv *port_priv - ); - -mlx_status -nodnic_port_add_mac_filter( - IN nodnic_port_priv *port_priv, - IN mlx_mac_address mac - ); - -mlx_status -nodnic_port_remove_mac_filter( - IN nodnic_port_priv *port_priv, - IN mlx_mac_address mac - ); -mlx_status -nodnic_port_add_mgid_filter( - IN nodnic_port_priv *port_priv, - IN mlx_mac_address mac - ); - -mlx_status -nodnic_port_remove_mgid_filter( - IN nodnic_port_priv *port_priv, - IN mlx_mac_address mac - ); -mlx_status -nodnic_port_thin_init( - IN nodnic_device_priv *device_priv, - IN nodnic_port_priv *port_priv, - IN mlx_uint8 port_index - ); - -mlx_status -nodnic_port_set_promisc( - IN nodnic_port_priv *port_priv, - IN mlx_boolean value - ); - -mlx_status -nodnic_port_set_promisc_multicast( - IN nodnic_port_priv *port_priv, - IN mlx_boolean value - ); - -mlx_status -nodnic_port_init( - IN nodnic_port_priv *port_priv - ); - -mlx_status -nodnic_port_close( - IN nodnic_port_priv *port_priv - ); - -mlx_status -nodnic_port_enable_dma( - IN nodnic_port_priv *port_priv - ); - -mlx_status -nodnic_port_disable_dma( - IN nodnic_port_priv *port_priv - ); - -mlx_status -nodnic_port_read_reset_needed( - IN nodnic_port_priv *port_priv, - OUT mlx_boolean *reset_needed - ); - -mlx_status -nodnic_port_read_port_management_change_event( - IN nodnic_port_priv *port_priv, - OUT mlx_boolean *change_event - ); -#endif /* STUB_NODNIC_PORT_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/src/mlx_cmd.c b/roms/ipxe/src/drivers/infiniband/mlx_nodnic/src/mlx_cmd.c deleted file mode 100644 index 69f85358b..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/src/mlx_cmd.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../include/mlx_cmd.h" -#include "../../mlx_utils/include/public/mlx_pci_gw.h" -#include "../../mlx_utils/include/public/mlx_bail.h" -#include "../../mlx_utils/include/public/mlx_pci.h" -#include "../../mlx_utils/include/public/mlx_logging.h" - -mlx_status -nodnic_cmd_read( - IN nodnic_device_priv *device_priv, - IN mlx_uint32 address, - OUT mlx_pci_gw_buffer *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_utils *utils = NULL; - - if ( device_priv == NULL || buffer == NULL ) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - utils = device_priv->utils; - - status = mlx_pci_gw_read(utils, PCI_GW_SPACE_NODNIC, address, buffer); - MLX_CHECK_STATUS(device_priv, status, read_error,"mlx_pci_gw_read failed"); - -read_error: -bad_param: - return status; -} - -mlx_status -nodnic_cmd_write( - IN nodnic_device_priv *device_priv, - IN mlx_uint32 address, - IN mlx_pci_gw_buffer buffer - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_utils *utils = NULL; - - - if ( device_priv == NULL ) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - utils = device_priv->utils; - - - status = mlx_pci_gw_write(utils, PCI_GW_SPACE_NODNIC, address, buffer); - MLX_CHECK_STATUS(device_priv, status, write_error,"mlx_pci_gw_write failed"); -write_error: -bad_param: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/src/mlx_device.c b/roms/ipxe/src/drivers/infiniband/mlx_nodnic/src/mlx_device.c deleted file mode 100644 index 4acc94fa6..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/src/mlx_device.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../include/mlx_device.h" -#include "../include/mlx_cmd.h" -#include "../../mlx_utils/include/public/mlx_bail.h" -#include "../../mlx_utils/include/public/mlx_pci.h" -#include "../../mlx_utils/include/public/mlx_memory.h" -#include "../../mlx_utils/include/public/mlx_logging.h" - -#define CHECK_BIT(field, offset) (((field) & ((mlx_uint32)1 << (offset))) != 0) - -static -mlx_status -check_nodnic_interface_supported( - IN nodnic_device_priv* device_priv, - OUT mlx_boolean *out - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 output = 0; - status = nodnic_cmd_read(device_priv, NODNIC_NIC_INTERFACE_SUPPORTED_OFFSET, - &output); - MLX_FATAL_CHECK_STATUS(status, read_error, "failed to read nic_interface_supported"); - *out = CHECK_BIT(output, NODNIC_NIC_INTERFACE_SUPPORTED_BIT); -read_error: - return status; -} - -static -mlx_status -wait_for_device_initialization( - IN nodnic_device_priv* device_priv - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint8 try = 0; - mlx_uint32 buffer = 0; - -#define CHECK_DEVICE_INIT_TRIES 10 - for( ; try < CHECK_DEVICE_INIT_TRIES ; try++){ - status = nodnic_cmd_read(device_priv, NODNIC_INITIALIZING_OFFSET, &buffer); - MLX_CHECK_STATUS(device_priv, status, read_error, "failed to read initializing"); - if( !CHECK_BIT(buffer, NODNIC_INITIALIZING_BIT)){ - goto init_done; - } - mlx_utils_delay_in_ms(100); - } - status = MLX_FAILED; -read_error: -init_done: - return status; -} - -static -mlx_status -disable_nodnic_inteface( - IN nodnic_device_priv *device_priv - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer = 0; - - buffer = (1 << NODNIC_DISABLE_INTERFACE_BIT); - status = nodnic_cmd_write(device_priv, NODNIC_CMDQ_PHY_ADDR_LOW_OFFSET, buffer); - MLX_FATAL_CHECK_STATUS(status, write_err, "failed to write cmdq_phy_addr + nic_interface"); - - status = wait_for_device_initialization(device_priv); - MLX_FATAL_CHECK_STATUS(status, init_err, "failed to initialize device"); -init_err: -write_err: - return status; -} -static -mlx_status -nodnic_device_start_nodnic( - IN nodnic_device_priv *device_priv - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer = 0; - mlx_boolean nodnic_supported = 0; - - status = wait_for_device_initialization(device_priv); - MLX_FATAL_CHECK_STATUS(status, wait_for_fw_err, "failed to initialize device"); - - status = check_nodnic_interface_supported(device_priv, &nodnic_supported); - MLX_FATAL_CHECK_STATUS(status, read_err,"failed to check nic_interface_supported"); - - if( nodnic_supported == 0 ){ - status = MLX_UNSUPPORTED; - goto nodnic_unsupported; - } - buffer = (1 << NODNIC_NIC_INTERFACE_BIT); - status = nodnic_cmd_write(device_priv, NODNIC_NIC_INTERFACE_OFFSET, buffer); - MLX_FATAL_CHECK_STATUS(status, write_err, "failed to write cmdq_phy_addr + nic_interface"); - - status = wait_for_device_initialization(device_priv); - MLX_FATAL_CHECK_STATUS(status, init_err, "failed to initialize device"); -init_err: -read_err: -write_err: -nodnic_unsupported: -wait_for_fw_err: - return status; -} - -static -mlx_status -nodnic_device_get_nodnic_data( - IN nodnic_device_priv *device_priv - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer = 0; - - status = nodnic_cmd_read(device_priv, NODNIC_LOCATION_OFFSET, &device_priv->device_offset); - MLX_FATAL_CHECK_STATUS(status, nodnic_offset_read_err, "failed to read nodnic offset"); - - status = nodnic_cmd_read(device_priv, - device_priv->device_offset + NODNIC_REVISION_OFFSET, &buffer); - MLX_FATAL_CHECK_STATUS(status, nodnic_revision_read_err, "failed to read nodnic revision"); - - device_priv->nodnic_revision = (buffer >> 24) & 0xFF; - if( device_priv->nodnic_revision != NODIC_SUPPORTED_REVISION ){ - MLX_DEBUG_ERROR(device_priv, "nodnic revision not supported\n"); - status = MLX_UNSUPPORTED; - goto unsupported_revision; - } - - status = nodnic_cmd_read(device_priv, - device_priv->device_offset + NODNIC_HARDWARE_FORMAT_OFFSET, &buffer); - MLX_FATAL_CHECK_STATUS(status, nodnic_hardware_format_read_err, "failed to read nodnic revision"); - device_priv->hardware_format = (buffer >> 16) & 0xFF; - - return status; - -unsupported_revision: -nodnic_hardware_format_read_err: -nodnic_offset_read_err: -nodnic_revision_read_err: - disable_nodnic_inteface(device_priv); - return status; -} - -mlx_status -nodnic_device_clear_int ( - IN nodnic_device_priv *device_priv - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 disable = 1; -#ifndef DEVICE_CX3 - status = nodnic_cmd_write(device_priv, NODNIC_NIC_DISABLE_INT_OFFSET, disable); - MLX_CHECK_STATUS(device_priv, status, clear_int_done, "failed writing to disable_bit"); -#else - mlx_utils *utils = device_priv->utils; - mlx_uint64 clear_int = (mlx_uint64)(device_priv->crspace_clear_int); - mlx_uint32 swapped = 0; - - if (device_priv->device_cap.crspace_doorbells == 0) { - status = nodnic_cmd_write(device_priv, NODNIC_NIC_DISABLE_INT_OFFSET, disable); - MLX_CHECK_STATUS(device_priv, status, clear_int_done, "failed writing to disable_bit"); - } else { - /* Write the new index and update FW that new data was submitted */ - disable = 0x80000000; - mlx_memory_cpu_to_be32(utils, disable, &swapped); - mlx_pci_mem_write (utils, MlxPciWidthUint32, 0, clear_int, 1, &swapped); - mlx_pci_mem_read (utils, MlxPciWidthUint32, 0, clear_int, 1, &swapped); - } -#endif -clear_int_done: - return status; -} - -mlx_status -nodnic_device_init( - IN nodnic_device_priv *device_priv - ) -{ - mlx_status status = MLX_SUCCESS; - - if( device_priv == NULL ){ - status = MLX_INVALID_PARAMETER; - goto parm_err; - } - status = nodnic_device_start_nodnic(device_priv); - MLX_FATAL_CHECK_STATUS(status, start_nodnic_err, "nodnic_device_start_nodnic failed"); - - status = nodnic_device_get_nodnic_data(device_priv); - MLX_FATAL_CHECK_STATUS(status, data_err, "nodnic_device_get_nodnic_data failed"); - return status; -data_err: -start_nodnic_err: -parm_err: - return status; -} - -mlx_status -nodnic_device_teardown( - IN nodnic_device_priv *device_priv - ) -{ - mlx_status status = MLX_SUCCESS; - status = disable_nodnic_inteface(device_priv); - MLX_FATAL_CHECK_STATUS(status, disable_failed, "failed to disable nodnic interface"); -disable_failed: - return status; -} - -mlx_status -nodnic_device_get_cap( - IN nodnic_device_priv *device_priv - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_capabilites *device_cap = NULL; - mlx_uint32 buffer = 0; - mlx_uint64 guid_l = 0; - mlx_uint64 guid_h = 0; - if( device_priv == NULL ){ - status = MLX_INVALID_PARAMETER; - goto parm_err; - } - - device_cap = &device_priv->device_cap; - - //get device capabilities - status = nodnic_cmd_read(device_priv, device_priv->device_offset + 0x0, &buffer); - MLX_FATAL_CHECK_STATUS(status, read_err, "failed to read nodnic first dword"); - -#define NODNIC_DEVICE_SUPPORT_MAC_FILTERS_OFFSET 15 -#define NODNIC_DEVICE_SUPPORT_PROMISC_FILTER_OFFSET 14 -#define NODNIC_DEVICE_SUPPORT_PROMISC_MULT_FILTER_OFFSET 13 -#define NODNIC_DEVICE_LOG_WORKING_BUFFER_SIZE_OFFSET 8 -#define NODNIC_DEVICE_LOG_WORKING_BUFFER_SIZE_MASK 0x7 -#define NODNIC_DEVICE_LOG_PKEY_TABLE_SIZE_OFFSET 4 -#define NODNIC_DEVICE_LOG_PKEY_TABLE_SIZE_MASK 0xF -#define NODNIC_DEVICE_NUM_PORTS_OFFSET 0 - device_cap->support_mac_filters = CHECK_BIT(buffer, NODNIC_DEVICE_SUPPORT_MAC_FILTERS_OFFSET); - - device_cap->support_promisc_filter = CHECK_BIT(buffer, NODNIC_DEVICE_SUPPORT_PROMISC_FILTER_OFFSET); - - device_cap->support_promisc_multicast_filter = CHECK_BIT(buffer, NODNIC_DEVICE_SUPPORT_PROMISC_MULT_FILTER_OFFSET); - - device_cap->log_working_buffer_size = - (buffer >> NODNIC_DEVICE_LOG_WORKING_BUFFER_SIZE_OFFSET) & NODNIC_DEVICE_LOG_WORKING_BUFFER_SIZE_MASK; - - device_cap->log_pkey_table_size = - (buffer >> NODNIC_DEVICE_LOG_PKEY_TABLE_SIZE_OFFSET) & NODNIC_DEVICE_LOG_PKEY_TABLE_SIZE_MASK; - - device_cap->num_ports = CHECK_BIT(buffer, NODNIC_DEVICE_NUM_PORTS_OFFSET) + 1; - -#ifdef DEVICE_CX3 -#define NODNIC_DEVICE_CRSPACE_DB_OFFSET 12 - device_cap->crspace_doorbells = CHECK_BIT(buffer, NODNIC_DEVICE_CRSPACE_DB_OFFSET); -#endif - - status = nodnic_cmd_read(device_priv, device_priv->device_offset + 0x4, &buffer); - MLX_FATAL_CHECK_STATUS(status, read_err, "failed to read nodnic second dword"); - -#define NODNIC_DEVICE_LOG_MAX_RING_SIZE_OFFSET 24 -#define NODNIC_DEVICE_LOG_MAX_RING_SIZE_MASK 0x3F -#define NODNIC_DEVICE_PD_MASK 0xFFFFFF - device_cap->log_max_ring_size = - (buffer >> NODNIC_DEVICE_LOG_MAX_RING_SIZE_OFFSET) & NODNIC_DEVICE_LOG_MAX_RING_SIZE_MASK; - - //get device magic numbers - device_priv->pd = buffer & NODNIC_DEVICE_PD_MASK; - - status = nodnic_cmd_read(device_priv, device_priv->device_offset + 0x8, &buffer); - MLX_FATAL_CHECK_STATUS(status, read_err, "failed to read nodnic third dword"); - device_priv->lkey = buffer; - -#ifdef DEVICE_CX3 - if ( device_cap->crspace_doorbells ) { - status = nodnic_cmd_read(device_priv, device_priv->device_offset + 0x18, &buffer); - MLX_FATAL_CHECK_STATUS(status, read_err, "failed to read nodnic_crspace_clear_int address"); - device_priv->crspace_clear_int = device_priv->utils->config + buffer; - } -#endif - - status = nodnic_cmd_read(device_priv, device_priv->device_offset + 0x10, (mlx_uint32*)&guid_h); - MLX_FATAL_CHECK_STATUS(status, read_err, "failed to read nodnic guid_h"); - status = nodnic_cmd_read(device_priv, device_priv->device_offset + 0x14, (mlx_uint32*)&guid_l); - MLX_FATAL_CHECK_STATUS(status, read_err, "failed to read nodnic guid_l"); - device_priv->device_guid = guid_l | (guid_h << 32); -read_err: -parm_err: - return status; -} - -mlx_status -nodnic_device_get_fw_version( - IN nodnic_device_priv *device_priv, - OUT mlx_uint16 *fw_ver_minor, - OUT mlx_uint16 *fw_ver_sub_minor, - OUT mlx_uint16 *fw_ver_major - ){ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer = 0; - - if( device_priv == NULL ){ - status = MLX_INVALID_PARAMETER; - goto parm_err; - } - - status = nodnic_cmd_read(device_priv, 0x0, &buffer); - MLX_CHECK_STATUS(device_priv, status, read_err, "failed to read fw revision major and minor"); - - *fw_ver_minor = (mlx_uint16)(buffer >> 16); - *fw_ver_major = (mlx_uint16)buffer; - - status = nodnic_cmd_read(device_priv, 0x4, &buffer); - MLX_CHECK_STATUS(device_priv, status, read_err, "failed to read fw revision sub minor"); - - *fw_ver_sub_minor = (mlx_uint16)buffer; -read_err: -parm_err: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/src/mlx_port.c b/roms/ipxe/src/drivers/infiniband/mlx_nodnic/src/mlx_port.c deleted file mode 100644 index a7afdab65..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_nodnic/src/mlx_port.c +++ /dev/null @@ -1,1038 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../include/mlx_port.h" -#include "../include/mlx_cmd.h" -#include "../../mlx_utils/include/public/mlx_memory.h" -#include "../../mlx_utils/include/public/mlx_pci.h" -#include "../../mlx_utils/include/public/mlx_bail.h" - -#define PortDataEntry( _option, _offset, _align, _mask) { \ - .option = _option, \ - .offset = _offset, \ - .align = _align, \ - .mask = _mask, \ - } - -#define QpDataEntry( _type, _send_offset, _recv_offset) { \ - .type = _type, \ - .send_offset = _send_offset, \ - .recv_offset = _recv_offset, \ - } - - -struct nodnic_port_data_entry nodnic_port_data_table[] = { - PortDataEntry(nodnic_port_option_link_type, 0x0, 4, 0x1), - PortDataEntry(nodnic_port_option_mac_low, 0xc, 0, 0xFFFFFFFF), - PortDataEntry(nodnic_port_option_mac_high, 0x8, 0, 0xFFFF), - PortDataEntry(nodnic_port_option_log_cq_size, 0x6c, 0, 0x3F), - PortDataEntry(nodnic_port_option_reset_needed, 0x0, 31, 0x1), - PortDataEntry(nodnic_port_option_mac_filters_en, 0x4, 0, 0x1F), - PortDataEntry(nodnic_port_option_port_state, 0x0, 0, 0xF), - PortDataEntry(nodnic_port_option_network_en, 0x4, 31, 0x1), - PortDataEntry(nodnic_port_option_dma_en, 0x4, 30, 0x1), - PortDataEntry(nodnic_port_option_eq_addr_low, 0x74, 0, 0xFFFFFFFF), - PortDataEntry(nodnic_port_option_eq_addr_high, 0x70, 0, 0xFFFFFFFF), - PortDataEntry(nodnic_port_option_cq_addr_low, 0x6c, 12, 0xFFFFF), - PortDataEntry(nodnic_port_option_cq_addr_high, 0x68, 0, 0xFFFFFFFF), - PortDataEntry(nodnic_port_option_port_management_change_event, 0x0, 30, 0x1), - PortDataEntry(nodnic_port_option_port_promisc_en, 0x4, 29, 0x1), - PortDataEntry(nodnic_port_option_arm_cq, 0x78, 8, 0xffff), - PortDataEntry(nodnic_port_option_port_promisc_multicast_en, 0x4, 28, 0x1), -#ifdef DEVICE_CX3 - PortDataEntry(nodnic_port_option_crspace_en, 0x4, 27, 0x1), -#endif -}; - -#define MAX_QP_DATA_ENTRIES 5 -struct nodnic_qp_data_entry nodnic_qp_data_teable[MAX_QP_DATA_ENTRIES] = { - QpDataEntry(NODNIC_QPT_SMI, 0, 0), - QpDataEntry(NODNIC_QPT_GSI, 0, 0), - QpDataEntry(NODNIC_QPT_UD, 0, 0), - QpDataEntry(NODNIC_QPT_RC, 0, 0), - QpDataEntry(NODNIC_QPT_ETH, 0x80, 0xC0), -}; - -#define MAX_NODNIC_PORTS 2 -int nodnic_port_offset_table[MAX_NODNIC_PORTS] = { - 0x100, //port 1 offset - 0x280, //port 1 offset -}; - -mlx_status -nodnic_port_get_state( - IN nodnic_port_priv *port_priv, - OUT nodnic_port_state *state - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 out = 0; - - status = nodnic_port_query(port_priv, - nodnic_port_option_port_state, &out); - MLX_CHECK_STATUS(port_priv->device, status, query_err, - "nodnic_port_query failed"); - *state = (nodnic_port_state)out; -query_err: - return status; -} -mlx_status -nodnic_port_get_type( - IN nodnic_port_priv *port_priv, - OUT nodnic_port_type *type - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 out = 0; - - if ( port_priv->port_type == NODNIC_PORT_TYPE_UNKNOWN){ - status = nodnic_port_query(port_priv, - nodnic_port_option_link_type, &out); - MLX_FATAL_CHECK_STATUS(status, query_err, - "nodnic_port_query failed"); - port_priv->port_type = (nodnic_port_type)out; - } - *type = port_priv->port_type; -query_err: - return status; -} - -mlx_status -nodnic_port_query( - IN nodnic_port_priv *port_priv, - IN nodnic_port_option option, - OUT mlx_uint32 *out - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = NULL; - struct nodnic_port_data_entry *data_entry; - mlx_uint32 buffer = 0; - if( port_priv == NULL || out == NULL){ - status = MLX_INVALID_PARAMETER; - goto invalid_parm; - } - device_priv = port_priv->device; - - data_entry = &nodnic_port_data_table[option]; - - status = nodnic_cmd_read(device_priv, - port_priv->port_offset + data_entry->offset , &buffer); - MLX_CHECK_STATUS(device_priv, status, read_err, - "nodnic_cmd_read failed"); - *out = (buffer >> data_entry->align) & data_entry->mask; -read_err: -invalid_parm: - return status; -} - -mlx_status -nodnic_port_set( - IN nodnic_port_priv *port_priv, - IN nodnic_port_option option, - IN mlx_uint32 in - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = NULL; - struct nodnic_port_data_entry *data_entry; - mlx_uint32 buffer = 0; - - if( port_priv == NULL ){ - MLX_DEBUG_FATAL_ERROR("port_priv is NULL\n"); - status = MLX_INVALID_PARAMETER; - goto invalid_parm; - } - device_priv = port_priv->device; - data_entry = &nodnic_port_data_table[option]; - - if( in > data_entry->mask ){ - MLX_DEBUG_FATAL_ERROR("in > data_entry->mask (%d > %d)\n", - in, data_entry->mask); - status = MLX_INVALID_PARAMETER; - goto invalid_parm; - } - status = nodnic_cmd_read(device_priv, - port_priv->port_offset + data_entry->offset, &buffer); - MLX_FATAL_CHECK_STATUS(status, read_err, - "nodnic_cmd_read failed"); - buffer = buffer & ~(data_entry->mask << data_entry->align); - buffer = buffer | (in << data_entry->align); - status = nodnic_cmd_write(device_priv, - port_priv->port_offset + data_entry->offset, buffer); - MLX_FATAL_CHECK_STATUS(status, write_err, - "nodnic_cmd_write failed"); -write_err: -read_err: -invalid_parm: - return status; -} - -mlx_status -nodnic_port_read_reset_needed( - IN nodnic_port_priv *port_priv, - OUT mlx_boolean *reset_needed - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 out = 0; - status = nodnic_port_query(port_priv, - nodnic_port_option_reset_needed, &out); - MLX_CHECK_STATUS(port_priv->device, status, query_err, - "nodnic_port_query failed"); - *reset_needed = (mlx_boolean)out; -query_err: - return status; -} - -mlx_status -nodnic_port_read_port_management_change_event( - IN nodnic_port_priv *port_priv, - OUT mlx_boolean *change_event - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 out = 0; - status = nodnic_port_query(port_priv, - nodnic_port_option_port_management_change_event, &out); - MLX_CHECK_STATUS(port_priv->device, status, query_err, - "nodnic_port_query failed"); - *change_event = (mlx_boolean)out; -query_err: - return status; -} - -mlx_status -nodnic_port_create_cq( - IN nodnic_port_priv *port_priv, - IN mlx_size cq_size, - OUT nodnic_cq **cq - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = NULL; - mlx_uint64 address = 0; - if( port_priv == NULL || cq == NULL){ - status = MLX_INVALID_PARAMETER; - goto invalid_parm; - } - - device_priv = port_priv->device; - - status = mlx_memory_zalloc(device_priv->utils, - sizeof(nodnic_cq),(mlx_void **)cq); - MLX_FATAL_CHECK_STATUS(status, alloc_err, - "cq priv allocation error"); - - (*cq)->cq_size = cq_size; - status = mlx_memory_alloc_dma(device_priv->utils, - (*cq)->cq_size, NODNIC_MEMORY_ALIGN, - &(*cq)->cq_virt); - MLX_FATAL_CHECK_STATUS(status, dma_alloc_err, - "cq allocation error"); - - status = mlx_memory_map_dma(device_priv->utils, - (*cq)->cq_virt, - (*cq)->cq_size, - &(*cq)->cq_physical, - &(*cq)->map); - MLX_FATAL_CHECK_STATUS(status, cq_map_err, - "cq map error"); - - /* update cq address */ -#define NODIC_CQ_ADDR_HIGH 0x68 -#define NODIC_CQ_ADDR_LOW 0x6c - address = (mlx_uint64)(*cq)->cq_physical; - nodnic_port_set(port_priv, nodnic_port_option_cq_addr_low, - (mlx_uint32)(address >> 12)); - address = address >> 32; - nodnic_port_set(port_priv, nodnic_port_option_cq_addr_high, - (mlx_uint32)address); - - return status; - mlx_memory_ummap_dma(device_priv->utils, (*cq)->map); -cq_map_err: - mlx_memory_free_dma(device_priv->utils, (*cq)->cq_size, - (void **)&((*cq)->cq_virt)); -dma_alloc_err: - mlx_memory_free(device_priv->utils, (void **)cq); -alloc_err: -invalid_parm: - return status; -} - -mlx_status -nodnic_port_destroy_cq( - IN nodnic_port_priv *port_priv, - IN nodnic_cq *cq - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = NULL; - - if( port_priv == NULL || cq == NULL){ - status = MLX_INVALID_PARAMETER; - goto invalid_parm; - } - device_priv = port_priv->device; - - mlx_memory_ummap_dma(device_priv->utils, cq->map); - - mlx_memory_free_dma(device_priv->utils, cq->cq_size, - (void **)&(cq->cq_virt)); - - mlx_memory_free(device_priv->utils, (void **)&cq); -invalid_parm: - return status; -} -mlx_status -nodnic_port_create_qp( - IN nodnic_port_priv *port_priv, - IN nodnic_queue_pair_type type, - IN mlx_size send_wq_size, - IN mlx_uint32 send_wqe_num, - IN mlx_size receive_wq_size, - IN mlx_uint32 recv_wqe_num, - OUT nodnic_qp **qp - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = NULL; - mlx_uint32 max_ring_size = 0; - mlx_uint64 address = 0; - mlx_uint32 log_size = 0; - if( port_priv == NULL || qp == NULL){ - status = MLX_INVALID_PARAMETER; - goto invalid_parm; - } - - device_priv = port_priv->device; - max_ring_size = (1 << device_priv->device_cap.log_max_ring_size); - if( send_wq_size > max_ring_size || - receive_wq_size > max_ring_size ){ - status = MLX_INVALID_PARAMETER; - goto invalid_parm; - } - - status = mlx_memory_zalloc(device_priv->utils, - sizeof(nodnic_qp),(mlx_void **)qp); - MLX_FATAL_CHECK_STATUS(status, alloc_err, - "qp allocation error"); - - if( nodnic_qp_data_teable[type].send_offset == 0 || - nodnic_qp_data_teable[type].recv_offset == 0){ - status = MLX_INVALID_PARAMETER; - goto invalid_type; - } - - (*qp)->send.nodnic_ring.offset = port_priv->port_offset + - nodnic_qp_data_teable[type].send_offset; - (*qp)->receive.nodnic_ring.offset = port_priv->port_offset + - nodnic_qp_data_teable[type].recv_offset; - - status = mlx_memory_alloc_dma(device_priv->utils, - send_wq_size, NODNIC_MEMORY_ALIGN, - (void*)&(*qp)->send.wqe_virt); - MLX_FATAL_CHECK_STATUS(status, send_alloc_err, - "send wq allocation error"); - - status = mlx_memory_alloc_dma(device_priv->utils, - receive_wq_size, NODNIC_MEMORY_ALIGN, - &(*qp)->receive.wqe_virt); - MLX_FATAL_CHECK_STATUS(status, receive_alloc_err, - "receive wq allocation error"); - - status = mlx_memory_map_dma(device_priv->utils, - (*qp)->send.wqe_virt, - send_wq_size, - &(*qp)->send.nodnic_ring.wqe_physical, - &(*qp)->send.nodnic_ring.map); - MLX_FATAL_CHECK_STATUS(status, send_map_err, - "send wq map error"); - - status = mlx_memory_map_dma(device_priv->utils, - (*qp)->receive.wqe_virt, - receive_wq_size, - &(*qp)->receive.nodnic_ring.wqe_physical, - &(*qp)->receive.nodnic_ring.map); - MLX_FATAL_CHECK_STATUS(status, receive_map_err, - "receive wq map error"); - - (*qp)->send.nodnic_ring.wq_size = send_wq_size; - (*qp)->send.nodnic_ring.num_wqes = send_wqe_num; - (*qp)->receive.nodnic_ring.wq_size = receive_wq_size; - (*qp)->receive.nodnic_ring.num_wqes = recv_wqe_num; - - /* Set Ownership bit in Send/receive queue (0 - recv ; 1 - send) */ - mlx_memory_set(device_priv->utils, (*qp)->send.wqe_virt, 0xff, send_wq_size ); - mlx_memory_set(device_priv->utils, (*qp)->receive.wqe_virt, 0, recv_wqe_num ); - - /* update send ring */ -#define NODIC_RING_QP_ADDR_HIGH 0x0 -#define NODIC_RING_QP_ADDR_LOW 0x4 - address = (mlx_uint64)(*qp)->send.nodnic_ring.wqe_physical; - status = nodnic_cmd_write(device_priv, (*qp)->send.nodnic_ring.offset + - NODIC_RING_QP_ADDR_HIGH, - (mlx_uint32)(address >> 32)); - MLX_FATAL_CHECK_STATUS(status, write_send_addr_err, - "send address write error 1"); - mlx_utils_ilog2((*qp)->send.nodnic_ring.wq_size, &log_size); - address = address | log_size; - status = nodnic_cmd_write(device_priv, (*qp)->send.nodnic_ring.offset + - NODIC_RING_QP_ADDR_LOW, - (mlx_uint32)address); - MLX_FATAL_CHECK_STATUS(status, write_send_addr_err, - "send address write error 2"); - /* update receive ring */ - address = (mlx_uint64)(*qp)->receive.nodnic_ring.wqe_physical; - status = nodnic_cmd_write(device_priv, (*qp)->receive.nodnic_ring.offset + - NODIC_RING_QP_ADDR_HIGH, - (mlx_uint32)(address >> 32)); - MLX_FATAL_CHECK_STATUS(status, write_recv_addr_err, - "receive address write error 1"); - mlx_utils_ilog2((*qp)->receive.nodnic_ring.wq_size, &log_size); - address = address | log_size; - status = nodnic_cmd_write(device_priv, (*qp)->receive.nodnic_ring.offset + - NODIC_RING_QP_ADDR_LOW, - (mlx_uint32)address); - MLX_FATAL_CHECK_STATUS(status, write_recv_addr_err, - "receive address write error 2"); - - return status; -write_recv_addr_err: -write_send_addr_err: - mlx_memory_ummap_dma(device_priv->utils, (*qp)->receive.nodnic_ring.map); -receive_map_err: - mlx_memory_ummap_dma(device_priv->utils, (*qp)->send.nodnic_ring.map); -send_map_err: - mlx_memory_free_dma(device_priv->utils, receive_wq_size, - &((*qp)->receive.wqe_virt)); -receive_alloc_err: - mlx_memory_free_dma(device_priv->utils, send_wq_size, - (void **)&((*qp)->send.wqe_virt)); -send_alloc_err: -invalid_type: - mlx_memory_free(device_priv->utils, (void **)qp); -alloc_err: -invalid_parm: - return status; -} - -mlx_status -nodnic_port_destroy_qp( - IN nodnic_port_priv *port_priv, - IN nodnic_queue_pair_type type __attribute__((unused)), - IN nodnic_qp *qp - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = port_priv->device; - - status = mlx_memory_ummap_dma(device_priv->utils, - qp->receive.nodnic_ring.map); - if( status != MLX_SUCCESS){ - MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status); - } - - status = mlx_memory_ummap_dma(device_priv->utils, qp->send.nodnic_ring.map); - if( status != MLX_SUCCESS){ - MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status); - } - - status = mlx_memory_free_dma(device_priv->utils, - qp->receive.nodnic_ring.wq_size, - (void **)&(qp->receive.wqe_virt)); - if( status != MLX_SUCCESS){ - MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status); - } - status = mlx_memory_free_dma(device_priv->utils, - qp->send.nodnic_ring.wq_size, - (void **)&(qp->send.wqe_virt)); - if( status != MLX_SUCCESS){ - MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status); - } - status = mlx_memory_free(device_priv->utils, (void **)&qp); - if( status != MLX_SUCCESS){ - MLX_DEBUG_ERROR(device_priv, "mlx_memory_free failed (Status = %d)\n", status); - } - return status; -} - -mlx_status -nodnic_port_get_qpn( - IN nodnic_port_priv *port_priv, - IN struct nodnic_ring *ring, - OUT mlx_uint32 *qpn - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer = 0; - if( ring == NULL || qpn == NULL){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - if( ring->qpn != 0 ){ - *qpn = ring->qpn; - goto success; - } -#define NODNIC_RING_QPN_OFFSET 0xc -#define NODNIC_RING_QPN_MASK 0xFFFFFF - status = nodnic_cmd_read(port_priv->device, - ring->offset + NODNIC_RING_QPN_OFFSET, - &buffer); - MLX_FATAL_CHECK_STATUS(status, read_err, - "nodnic_cmd_read failed"); - ring->qpn = buffer & NODNIC_RING_QPN_MASK; - *qpn = ring->qpn; -read_err: -success: -bad_param: - return status; -} - -#ifdef DEVICE_CX3 -static -mlx_status -nodnic_port_send_db_connectx3( - IN nodnic_port_priv *port_priv, - IN struct nodnic_ring *ring __attribute__((unused)), - IN mlx_uint16 index - ) -{ - nodnic_port_data_flow_gw *ptr = port_priv->data_flow_gw; - mlx_uint32 index32 = index; - mlx_pci_mem_write(port_priv->device->utils, MlxPciWidthUint32, 0, - (mlx_uint64)&(ptr->send_doorbell), 1, &index32); - return MLX_SUCCESS; -} - -static -mlx_status -nodnic_port_recv_db_connectx3( - IN nodnic_port_priv *port_priv, - IN struct nodnic_ring *ring __attribute__((unused)), - IN mlx_uint16 index - ) -{ - nodnic_port_data_flow_gw *ptr = port_priv->data_flow_gw; - mlx_uint32 index32 = index; - mlx_pci_mem_write(port_priv->device->utils, MlxPciWidthUint32, 0, - (mlx_uint64)&(ptr->recv_doorbell), 1, &index32); - return MLX_SUCCESS; -} -#endif - -mlx_status -nodnic_port_update_ring_doorbell( - IN nodnic_port_priv *port_priv, - IN struct nodnic_ring *ring, - IN mlx_uint16 index - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer = 0; - if( ring == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } -#define NODNIC_RING_RING_OFFSET 0x8 - buffer = (mlx_uint32)((index & 0xFFFF)<< 8); - status = nodnic_cmd_write(port_priv->device, - ring->offset + NODNIC_RING_RING_OFFSET, - buffer); - MLX_CHECK_STATUS(port_priv->device, status, write_err, - "nodnic_cmd_write failed"); -write_err: -bad_param: - return status; -} - -mlx_status -nodnic_port_get_cq_size( - IN nodnic_port_priv *port_priv, - OUT mlx_uint64 *cq_size - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 out = 0; - status = nodnic_port_query(port_priv, nodnic_port_option_log_cq_size, &out); - MLX_FATAL_CHECK_STATUS(status, query_err, - "nodnic_port_query failed"); - *cq_size = 1 << out; -query_err: - return status; -} - -mlx_status -nodnic_port_allocate_eq( - IN nodnic_port_priv *port_priv, - IN mlx_uint8 log_eq_size - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = NULL; - mlx_uint64 address = 0; - - if( port_priv == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - device_priv = port_priv->device; - port_priv->eq.eq_size = ( ( 1 << log_eq_size ) * 1024 ); /* Size is in KB */ - status = mlx_memory_alloc_dma(device_priv->utils, - port_priv->eq.eq_size, - NODNIC_MEMORY_ALIGN, - &port_priv->eq.eq_virt); - MLX_FATAL_CHECK_STATUS(status, alloc_err, - "eq allocation error"); - - status = mlx_memory_map_dma(device_priv->utils, - port_priv->eq.eq_virt, - port_priv->eq.eq_size, - &port_priv->eq.eq_physical, - &port_priv->eq.map); - MLX_FATAL_CHECK_STATUS(status, map_err, - "eq map error"); - - address = port_priv->eq.eq_physical; - status = nodnic_port_set(port_priv, nodnic_port_option_eq_addr_low, - (mlx_uint32)address); - MLX_FATAL_CHECK_STATUS(status, set_err, - "failed to set eq addr low"); - address = (address >> 32); - status = nodnic_port_set(port_priv, nodnic_port_option_eq_addr_high, - (mlx_uint32)address); - MLX_FATAL_CHECK_STATUS(status, set_err, - "failed to set eq addr high"); - return status; -set_err: - mlx_memory_ummap_dma(device_priv->utils, port_priv->eq.map); -map_err: - mlx_memory_free_dma(device_priv->utils, - port_priv->eq.eq_size, - (void **)&(port_priv->eq.eq_virt)); -alloc_err: -bad_param: - return status; -} -mlx_status -nodnic_port_free_eq( - IN nodnic_port_priv *port_priv - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device_priv = NULL; - - if( port_priv == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - device_priv = port_priv->device; - mlx_memory_ummap_dma(device_priv->utils, port_priv->eq.map); - - mlx_memory_free_dma(device_priv->utils, - port_priv->eq.eq_size, - (void **)&(port_priv->eq.eq_virt)); - -bad_param: - return status; -} - -mlx_status -nodnic_port_add_mac_filter( - IN nodnic_port_priv *port_priv, - IN mlx_mac_address mac - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device= NULL;; - mlx_uint8 index = 0; - mlx_uint32 out = 0; - mlx_uint32 mac_filters_en = 0; - mlx_uint32 address = 0; - mlx_mac_address zero_mac; - mlx_utils *utils = NULL; - - if( port_priv == NULL){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - memset(&zero_mac, 0, sizeof(zero_mac)); - - device = port_priv->device; - utils = device->utils; - - /* check if mac already exists */ - for( ; index < NODNIC_MAX_MAC_FILTERS ; index ++) { - mlx_memory_cmp(utils, &port_priv->mac_filters[index], &mac, - sizeof(mac), &out); - if ( out == 0 ){ - status = MLX_FAILED; - goto already_exists; - } - } - - /* serch for available mac filter slot */ - for (index = 0 ; index < NODNIC_MAX_MAC_FILTERS ; index ++) { - mlx_memory_cmp(utils, &port_priv->mac_filters[index], &zero_mac, - sizeof(zero_mac), &out); - if ( out == 0 ){ - break; - } - } - if ( index >= NODNIC_MAX_MAC_FILTERS ){ - status = MLX_FAILED; - goto mac_list_full; - } - - status = nodnic_port_query(port_priv, nodnic_port_option_mac_filters_en, - &mac_filters_en); - MLX_CHECK_STATUS(device, status , query_err, - "nodnic_port_query failed"); - if(mac_filters_en & (1 << index)){ - status = MLX_FAILED; - goto mac_list_full; - } - port_priv->mac_filters[index] = mac; - - // set mac filter - address = port_priv->port_offset + NODNIC_PORT_MAC_FILTERS_OFFSET + - (0x8 * index); - - status = nodnic_cmd_write(device, address, mac.high ); - MLX_CHECK_STATUS(device, status, write_err, "set mac high failed"); - status = nodnic_cmd_write(device, address + 0x4, mac.low ); - MLX_CHECK_STATUS(device, status, write_err, "set mac low failed"); - - // enable mac filter - mac_filters_en = mac_filters_en | (1 << index); - status = nodnic_port_set(port_priv, nodnic_port_option_mac_filters_en, - mac_filters_en); - MLX_CHECK_STATUS(device, status , set_err, - "nodnic_port_set failed"); -set_err: -write_err: -query_err: -mac_list_full: -already_exists: -bad_param: - return status; -} - -mlx_status -nodnic_port_remove_mac_filter( - IN nodnic_port_priv *port_priv, - IN mlx_mac_address mac - ) -{ - mlx_status status = MLX_SUCCESS; - nodnic_device_priv *device= NULL;; - mlx_uint8 index = 0; - mlx_uint32 out = 0; - mlx_uint32 mac_filters_en = 0; - mlx_mac_address zero_mac; - mlx_utils *utils = NULL; - - if( port_priv == NULL){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - memset(&zero_mac, 0, sizeof(zero_mac)); - - device = port_priv->device; - utils = device->utils; - - /* serch for mac filter */ - for( ; index < NODNIC_MAX_MAC_FILTERS ; index ++) { - mlx_memory_cmp(utils, &port_priv->mac_filters[index], &mac, - sizeof(mac), &out); - if ( out == 0 ){ - break; - } - } - if ( index == NODNIC_MAX_MAC_FILTERS ){ - status = MLX_FAILED; - goto mac_not_found; - } - - status = nodnic_port_query(port_priv, nodnic_port_option_mac_filters_en, - &mac_filters_en); - MLX_CHECK_STATUS(device, status , query_err, - "nodnic_port_query failed"); - if((mac_filters_en & (1 << index)) == 0){ - status = MLX_FAILED; - goto mac_not_en; - } - port_priv->mac_filters[index] = zero_mac; - - // disable mac filter - mac_filters_en = mac_filters_en & ~(1 << index); - status = nodnic_port_set(port_priv, nodnic_port_option_mac_filters_en, - mac_filters_en); - MLX_CHECK_STATUS(device, status , set_err, - "nodnic_port_set failed"); -set_err: -query_err: -mac_not_en: -mac_not_found: -bad_param: - return status; -} - -static -mlx_status -nodnic_port_set_network( - IN nodnic_port_priv *port_priv, - IN mlx_boolean value - ) -{ - mlx_status status = MLX_SUCCESS; - /*mlx_uint32 network_valid = 0; - mlx_uint8 try = 0;*/ - - status = nodnic_port_set(port_priv, nodnic_port_option_network_en, value); - MLX_CHECK_STATUS(port_priv->device, status, set_err, - "nodnic_port_set failed"); - port_priv->network_state = value; -set_err: - return status; -} - -#ifdef DEVICE_CX3 -static -mlx_status -nodnic_port_set_dma_connectx3( - IN nodnic_port_priv *port_priv, - IN mlx_boolean value - ) -{ - mlx_utils *utils = port_priv->device->utils; - nodnic_port_data_flow_gw *ptr = port_priv->data_flow_gw; - mlx_uint32 data = (value ? 0xffffffff : 0x0); - mlx_pci_mem_write(utils, MlxPciWidthUint32, 0, - (mlx_uint64)&(ptr->dma_en), 1, &data); - return MLX_SUCCESS; -} -#endif - -static -mlx_status -nodnic_port_set_dma( - IN nodnic_port_priv *port_priv, - IN mlx_boolean value - ) -{ - return nodnic_port_set(port_priv, nodnic_port_option_dma_en, value); -} - -static -mlx_status -nodnic_port_check_and_set_dma( - IN nodnic_port_priv *port_priv, - IN mlx_boolean value - ) -{ - mlx_status status = MLX_SUCCESS; - if ( port_priv->dma_state == value ) { - MLX_DEBUG_WARN(port_priv->device, - "nodnic_port_check_and_set_dma: already %s\n", - (value ? "enabled" : "disabled")); - status = MLX_SUCCESS; - goto set_out; - } - - status = port_priv->set_dma(port_priv, value); - MLX_CHECK_STATUS(port_priv->device, status, set_err, - "nodnic_port_set failed"); - port_priv->dma_state = value; -set_err: -set_out: - return status; -} - - -mlx_status -nodnic_port_set_promisc( - IN nodnic_port_priv *port_priv, - IN mlx_boolean value - ){ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer = value; - - status = nodnic_port_set(port_priv, nodnic_port_option_port_promisc_en, buffer); - MLX_CHECK_STATUS(port_priv->device, status, set_err, - "nodnic_port_set failed"); -set_err: - return status; -} - -mlx_status -nodnic_port_set_promisc_multicast( - IN nodnic_port_priv *port_priv, - IN mlx_boolean value - ){ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer = value; - - status = nodnic_port_set(port_priv, nodnic_port_option_port_promisc_multicast_en, buffer); - MLX_CHECK_STATUS(port_priv->device, status, set_err, - "nodnic_port_set failed"); -set_err: - return status; -} - -mlx_status -nodnic_port_init( - IN nodnic_port_priv *port_priv - ) -{ - mlx_status status = MLX_SUCCESS; - - if( port_priv == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = nodnic_port_set_network(port_priv, TRUE); - MLX_FATAL_CHECK_STATUS(status, set_err, - "nodnic_port_set_network failed"); -set_err: -bad_param: - return status; -} - -mlx_status -nodnic_port_close( - IN nodnic_port_priv *port_priv - ) -{ - mlx_status status = MLX_SUCCESS; - - if( port_priv == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = nodnic_port_set_network(port_priv, FALSE); - MLX_FATAL_CHECK_STATUS(status, set_err, - "nodnic_port_set_network failed"); -set_err: -bad_param: - return status; -} - -mlx_status -nodnic_port_enable_dma( - IN nodnic_port_priv *port_priv - ) -{ - mlx_status status = MLX_SUCCESS; - - if( port_priv == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = nodnic_port_check_and_set_dma(port_priv, TRUE); - MLX_CHECK_STATUS(port_priv->device, status, set_err, - "nodnic_port_check_and_set_dma failed"); -set_err: -bad_param: - return status; -} - -mlx_status -nodnic_port_disable_dma( - IN nodnic_port_priv *port_priv - ) -{ - mlx_status status = MLX_SUCCESS; - - if( port_priv == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = nodnic_port_check_and_set_dma(port_priv, FALSE); - MLX_CHECK_STATUS(port_priv->device, status, set_err, - "nodnic_port_check_and_set_dma failed"); -set_err: -bad_param: - return status; -} - -mlx_status -nodnic_port_thin_init( - IN nodnic_device_priv *device_priv, - IN nodnic_port_priv *port_priv, - IN mlx_uint8 port_index - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_boolean reset_needed = 0; -#ifdef DEVICE_CX3 - mlx_uint32 offset; -#endif - - if( device_priv == NULL || port_priv == NULL || port_index > 1){ - status = MLX_INVALID_PARAMETER; - goto invalid_parm; - } - - port_priv->device = device_priv; - - port_priv->port_offset = device_priv->device_offset + - nodnic_port_offset_table[port_index]; - - port_priv->port_num = port_index + 1; - - port_priv->send_doorbell = nodnic_port_update_ring_doorbell; - port_priv->recv_doorbell = nodnic_port_update_ring_doorbell; - port_priv->set_dma = nodnic_port_set_dma; -#ifdef DEVICE_CX3 - if (device_priv->device_cap.crspace_doorbells) { - status = nodnic_cmd_read(device_priv, (port_priv->port_offset + 0x100), - &offset); - if (status != MLX_SUCCESS) { - return status; - } else { - port_priv->data_flow_gw = (nodnic_port_data_flow_gw *) - (device_priv->utils->config + offset); - } - if ( nodnic_port_set ( port_priv, nodnic_port_option_crspace_en, 1 ) ) { - return MLX_FAILED; - } - port_priv->send_doorbell = nodnic_port_send_db_connectx3; - port_priv->recv_doorbell = nodnic_port_recv_db_connectx3; - port_priv->set_dma = nodnic_port_set_dma_connectx3; - } -#endif - /* clear reset_needed */ - nodnic_port_read_reset_needed(port_priv, &reset_needed); - - port_priv->port_type = NODNIC_PORT_TYPE_UNKNOWN; -invalid_parm: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/private/mlx_memory_priv.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/private/mlx_memory_priv.h deleted file mode 100644 index 1f8ba89ea..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/private/mlx_memory_priv.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef MLXUTILS_INCLUDE_PRIVATE_MEMORYPRIV_H_ -#define MLXUTILS_INCLUDE_PRIVATE_MEMORYPRIV_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../../mlx_utils/include/public/mlx_utils.h" - -mlx_status -mlx_memory_alloc_priv( - IN mlx_utils *utils, - IN mlx_size size, - OUT mlx_void **ptr - ); - -mlx_status -mlx_memory_zalloc_priv( - IN mlx_utils *utils, - IN mlx_size size, - OUT mlx_void **ptr - ); - -mlx_status -mlx_memory_free_priv( - IN mlx_utils *utils, - IN mlx_void *ptr - ); -mlx_status -mlx_memory_alloc_dma_priv( - IN mlx_utils *utils, - IN mlx_size size , - IN mlx_size align, - OUT mlx_void **ptr - ); - -mlx_status -mlx_memory_free_dma_priv( - IN mlx_utils *utils, - IN mlx_size size , - IN mlx_void *ptr - ); -mlx_status -mlx_memory_map_dma_priv( - IN mlx_utils *utils, - IN mlx_void *addr , - IN mlx_size number_of_bytes, - OUT mlx_physical_address *phys_addr, - OUT mlx_void **mapping - ); - -mlx_status -mlx_memory_ummap_dma_priv( - IN mlx_utils *utils, - IN mlx_void *mapping - ); - -mlx_status -mlx_memory_cmp_priv( - IN mlx_utils *utils, - IN mlx_void *first_block, - IN mlx_void *second_block, - IN mlx_size size, - OUT mlx_uint32 *out - ); - -mlx_status -mlx_memory_set_priv( - IN mlx_utils *utils, - IN mlx_void *block, - IN mlx_int32 value, - IN mlx_size size - ); - -mlx_status -mlx_memory_cpy_priv( - IN mlx_utils *utils, - OUT mlx_void *destination_buffer, - IN mlx_void *source_buffer, - IN mlx_size length - ); - -mlx_status -mlx_memory_cpu_to_be32_priv( - IN mlx_utils *utils, - IN mlx_uint32 source, - IN mlx_uint32 *destination - ); - -mlx_status -mlx_memory_be32_to_cpu_priv( - IN mlx_utils *utils, - IN mlx_uint32 source, - IN mlx_uint32 *destination - ); -#endif /* STUB_MLXUTILS_INCLUDE_PRIVATE_MEMORYPRIV_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/private/mlx_pci_priv.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/private/mlx_pci_priv.h deleted file mode 100644 index 89cad75eb..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/private/mlx_pci_priv.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef STUB_MLXUTILS_INCLUDE_PRIVATE_PCIPRIV_H_ -#define STUB_MLXUTILS_INCLUDE_PRIVATE_PCIPRIV_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../include/public/mlx_pci.h" -#include "../../include/public/mlx_utils.h" - -mlx_status -mlx_pci_init_priv( - IN mlx_utils *utils - ); - -mlx_status -mlx_pci_read_priv( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint32 offset, - IN mlx_uintn count, - OUT mlx_void *buffer - ); - -mlx_status -mlx_pci_write_priv( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint32 offset, - IN mlx_uintn count, - IN mlx_void *buffer - ); - -mlx_status -mlx_pci_mem_read_priv( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint8 bar_index, - IN mlx_uint64 offset, - IN mlx_uintn count, - OUT mlx_void *buffer - ); - -mlx_status -mlx_pci_mem_write_priv( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint8 bar_index, - IN mlx_uint64 offset, - IN mlx_uintn count, - IN mlx_void *buffer - ); - - -#endif /* STUB_MLXUTILS_INCLUDE_PRIVATE_PCIPRIV_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/private/mlx_utils_priv.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/private/mlx_utils_priv.h deleted file mode 100644 index 268b76fad..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/private/mlx_utils_priv.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef SRC_DRIVERS_INFINIBAND_MLX_UTILS_INCLUDE_PRIVATE_MLX_UTILS_PRIV_H_ -#define SRC_DRIVERS_INFINIBAND_MLX_UTILS_INCLUDE_PRIVATE_MLX_UTILS_PRIV_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../include/public/mlx_utils.h" - -mlx_status -mlx_utils_delay_in_ms_priv( - IN mlx_uint32 msecs - ); - -mlx_status -mlx_utils_delay_in_us_priv( - IN mlx_uint32 usecs - ); - -mlx_status -mlx_utils_ilog2_priv( - IN mlx_uint32 i, - OUT mlx_uint32 *log - ); - -mlx_status -mlx_utils_init_lock_priv( - OUT void **lock - ); - -mlx_status -mlx_utils_free_lock_priv( - IN void *lock - ); - -mlx_status -mlx_utils_acquire_lock_priv ( - IN void *lock - ); - -mlx_status -mlx_utils_release_lock_priv ( - IN void *lock - ); - -mlx_status -mlx_utils_rand_priv ( - IN mlx_utils *utils, - OUT mlx_uint32 *rand_num - ); -#endif /* SRC_DRIVERS_INFINIBAND_MLX_UTILS_INCLUDE_PRIVATE_MLX_UTILS_PRIV_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_bail.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_bail.h deleted file mode 100644 index a4f4b37b1..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_bail.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef INCLUDE_PUBLIC_MLXBAIL_H_ -#define INCLUDE_PUBLIC_MLXBAIL_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_types.h" - -#define MLX_BAIL_ERROR(id, status,message) MLX_CHECK_STATUS(id, status, bail, message) - -#define MLX_FATAL_CHECK_STATUS(status, label, message) \ - do { \ - if (status != MLX_SUCCESS) { \ - MLX_DEBUG_FATAL_ERROR(message " (Status = %d)\n", status); \ - goto label; \ - } \ - } while (0) - -#define MLX_CHECK_STATUS(id, status, label, message) \ - do { \ - if (status != MLX_SUCCESS) { \ - MLX_DEBUG_ERROR(id, message " (Status = %d)\n", status);\ - goto label; \ - } \ - } while (0) - - - -#endif /* INCLUDE_PUBLIC_MLXBAIL_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_icmd.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_icmd.h deleted file mode 100644 index 1ed423daf..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_icmd.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef MLXUTILS_INCLUDE_PUBLIC_MLX_ICMD_H_ -#define MLXUTILS_INCLUDE_PUBLIC_MLX_ICMD_H_ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_utils.h" - -#define MLX_ICMD_MB_ADDR 0x100000 -#define MLX_ICMD_MB_SIZE_ADDR 0x1000 -#define MLX_ICMD_CTRL_ADDR 0x0 - -#define MLX_ICMD_SEMAPHORE_ADDR 0x0 - -#define MLX_ICMD_SEMAPHORE_ID 1234 - -enum { - FLASH_REG_ACCESS = 0x9001, - GET_FW_INFO = 0x8007, - QUERY_VIRTUAL_MAC = 0x9003, - SET_VIRTUAL_MAC = 0x9004, - QUERY_WOL_ROL = 0x9005, - SET_WOL_ROL = 0x9006, - OCBB_INIT = 0x9007, - OCBB_QUERY_HEADER_STATUS = 0x9008, - OCBB_QUERY_ETOC_STATUS = 0x9009, - OCBB_QUERY_SET_EVENT = 0x900A, - OCSD_INIT = 0xf004, -}; - -struct mlx_icmd_ocsd { - mlx_uint32 reserved; - mlx_uint64 address; -}; - -mlx_status -mlx_icmd_send_command( - IN mlx_utils *utils, - IN mlx_uint16 opcode, - IN OUT mlx_void* data, - IN mlx_uint32 write_data_size, - IN mlx_uint32 read_data_size - ); - -#endif /* MLXUTILS_INCLUDE_PUBLIC_MLX_ICMD_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_logging.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_logging.h deleted file mode 100644 index 7b7b852d1..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_logging.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef PUBLIC_INCLUDE_MLX_LOGGER_H_ -#define PUBLIC_INCLUDE_MLX_LOGGER_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../../mlx_utils_flexboot/include/mlx_logging_priv.h" - -#define MLX_DEBUG_FATAL_ERROR(...) MLX_DEBUG_FATAL_ERROR_PRIVATE(__VA_ARGS__) -#define MLX_DEBUG_ERROR(...) MLX_DEBUG_ERROR_PRIVATE(__VA_ARGS__) -#define MLX_DEBUG_WARN(...) MLX_DEBUG_WARN_PRIVATE(__VA_ARGS__) -#define MLX_DEBUG_INFO1(...) MLX_DEBUG_INFO1_PRIVATE(__VA_ARGS__) -#define MLX_DEBUG_INFO2(...) MLX_DEBUG_INFO2_PRIVATE(__VA_ARGS__) -#define MLX_DBG_ERROR(...) MLX_DBG_ERROR_PRIVATE(__VA_ARGS__) -#define MLX_DBG_WARN(...) MLX_DBG_WARN_PRIVATE(__VA_ARGS__) -#define MLX_DBG_INFO1(...) MLX_DBG_INFO1_PRIVATE(__VA_ARGS__) -#define MLX_DBG_INFO2(...) MLX_DBG_INFO2_PRIVATE(__VA_ARGS__) - -#define MLX_TRACE_1_START() MLX_DBG_INFO1_PRIVATE("Start\n") -#define MLX_TRACE_1_END() MLX_DBG_INFO1_PRIVATE("End\n") -#define MLX_TRACE_1_END_STATUS(status) MLX_DBG_INFO1_PRIVATE("End (%s=%d)\n", #status,status) -#define MLX_TRACE_2_START() MLX_DBG_INFO2_PRIVATE("Start\n") -#define MLX_TRACE_2_END() MLX_DBG_INFO2_PRIVATE("End\n") -#define MLX_TRACE_2_END_STATUS(status) MLX_DBG_INFO2_PRIVATE("End (%s=%d)\n", #status,status) - - - -#endif /* PUBLIC_INCLUDE_MLX_LOGGER_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_memory.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_memory.h deleted file mode 100644 index 056756666..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_memory.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef MLXUTILS_INCLUDE_PUBLIC_MEMORY_H_ -#define MLXUTILS_INCLUDE_PUBLIC_MEMORY_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_utils.h" - - -mlx_status -mlx_memory_alloc( - IN mlx_utils *utils, - IN mlx_size size, - OUT mlx_void **ptr - ); - -mlx_status -mlx_memory_zalloc( - IN mlx_utils *utils, - IN mlx_size size, - OUT mlx_void **ptr - ); - -mlx_status -mlx_memory_free( - IN mlx_utils *utils, - IN mlx_void **ptr - ); -mlx_status -mlx_memory_alloc_dma( - IN mlx_utils *utils, - IN mlx_size size , - IN mlx_size align, - OUT mlx_void **ptr - ); - -mlx_status -mlx_memory_free_dma( - IN mlx_utils *utils, - IN mlx_size size , - IN mlx_void **ptr - ); -mlx_status -mlx_memory_map_dma( - IN mlx_utils *utils, - IN mlx_void *Addr , - IN mlx_size NumberOfBytes, - OUT mlx_physical_address *PhysAddr, - OUT mlx_void **Mapping - ); - -mlx_status -mlx_memory_ummap_dma( - IN mlx_utils *utils, - IN mlx_void *Mapping - ); - -mlx_status -mlx_memory_cmp( - IN mlx_utils *utils, - IN mlx_void *first_block, - IN mlx_void *second_block, - IN mlx_size size, - OUT mlx_uint32 *out - ); - -mlx_status -mlx_memory_set( - IN mlx_utils *utils, - IN mlx_void *block, - IN mlx_int32 value, - IN mlx_size size - ); - -mlx_status -mlx_memory_cpy( - IN mlx_utils *utils, - OUT mlx_void *destination_buffer, - IN mlx_void *source_buffer, - IN mlx_size length - ); - -mlx_status -mlx_memory_cpu_to_be32( - IN mlx_utils *utils, - IN mlx_uint32 source, - IN mlx_uint32 *destination - ); - -mlx_status -mlx_memory_be32_to_cpu( - IN mlx_utils *utils, - IN mlx_uint32 source, - IN mlx_uint32 *destination - ); - -#endif /* STUB_MLXUTILS_INCLUDE_PUBLIC_MEMORY_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_pci.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_pci.h deleted file mode 100644 index 416bdb66b..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_pci.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef STUB_MLXUTILS_INCLUDE_PUBLIC_PCI_H_ -#define STUB_MLXUTILS_INCLUDE_PUBLIC_PCI_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_utils.h" - -typedef enum { - MlxPciWidthUint8 = 0, - MlxPciWidthUint16, - MlxPciWidthUint32, - MlxPciWidthUint64, -} mlx_pci_width; - -mlx_status -mlx_pci_init( - IN mlx_utils *utils - ); - -mlx_status -mlx_pci_read( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint32 offset, - IN mlx_uintn count, - OUT mlx_void *buffer - ); - -mlx_status -mlx_pci_write( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint32 offset, - IN mlx_uintn count, - IN mlx_void *buffer - ); - -mlx_status -mlx_pci_mem_read( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint8 bar_index, - IN mlx_uint64 offset, - IN mlx_uintn count, - OUT mlx_void *buffer - ); - -mlx_status -mlx_pci_mem_write( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint8 bar_index, - IN mlx_uint64 offset, - IN mlx_uintn count, - IN mlx_void *buffer - ); - - -#endif /* STUB_MLXUTILS_INCLUDE_PUBLIC_PCI_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_pci_gw.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_pci_gw.h deleted file mode 100644 index c074a22e5..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_pci_gw.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef INCLUDE_PUBLIC_MLX_PCI_GW_H_ -#define INCLUDE_PUBLIC_MLX_PCI_GW_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_utils.h" - -#define PCI_GW_FIRST_CAPABILITY_POINTER_OFFSET 0x34 - -#define PCI_GW_CAPABILITY_ID 0x9 - -#define PCI_GW_CAPABILITY_ID_OFFSET 0x0 -#define PCI_GW_CAPABILITY_NEXT_POINTER_OFFSET 0x1 -#define PCI_GW_CAPABILITY_SPACE_OFFSET 0x4 -#define PCI_GW_CAPABILITY_STATUS_OFFSET 0x7 -#define PCI_GW_CAPABILITY_COUNTER_OFFSET 0x8 -#define PCI_GW_CAPABILITY_SEMAPHORE_OFFSET 0xC -#define PCI_GW_CAPABILITY_ADDRESS_OFFSET 0x10 -#define PCI_GW_CAPABILITY_FLAG_OFFSET 0x10 -#define PCI_GW_CAPABILITY_DATA_OFFSET 0x14 - -#define PCI_GW_SEMPHORE_TRIES 3000000 -#define PCI_GW_GET_OWNERSHIP_TRIES 5000 -#define PCI_GW_READ_FLAG_TRIES 3000000 - -#define PCI_GW_WRITE_FLAG 0x80000000 - -#define PCI_GW_SPACE_NODNIC 0x4 -#define PCI_GW_SPACE_ALL_ICMD 0x3 -#define PCI_GW_SPACE_SEMAPHORE 0xa -#define PCI_GW_SPACE_CR0 0x2 - -typedef mlx_uint32 mlx_pci_gw_buffer; - - -mlx_status -mlx_pci_gw_init( - IN mlx_utils *utils - ); -mlx_status -mlx_pci_gw_teardown( - IN mlx_utils *utils - ); -mlx_status -mlx_pci_gw_read( - IN mlx_utils *utils, - IN mlx_pci_gw_space space, - IN mlx_uint32 address, - OUT mlx_pci_gw_buffer *buffer - ); - -mlx_status -mlx_pci_gw_write( - IN mlx_utils *utils, - IN mlx_pci_gw_space space, - IN mlx_uint32 address, - IN mlx_pci_gw_buffer buffer - ); - - - -#endif /* INCLUDE_PUBLIC_MLX_PCI_GW_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_types.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_types.h deleted file mode 100644 index 9c66567a3..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_types.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef INCLUDE_PUBLIC_MLXTYPES_H_ -#define INCLUDE_PUBLIC_MLXTYPES_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../../mlx_utils_flexboot/include/mlx_types_priv.h" - -#endif /* INCLUDE_PUBLIC_MLXBAIL_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_utils.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_utils.h deleted file mode 100644 index 46ad97c3b..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/include/public/mlx_utils.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef MLXUTILS_INCLUDE_PUBLIC_MLXUTILS_H_ -#define MLXUTILS_INCLUDE_PUBLIC_MLXUTILS_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_logging.h" -#include "mlx_types.h" - -#define IN -#define OUT - -typedef mlx_uint16 mlx_pci_gw_space; - -typedef struct{ - mlx_uint32 pci_cmd_offset; - mlx_pci_gw_space space; -} __attribute__ (( packed )) mlx_pci_gw; - -typedef struct { - mlx_boolean icmd_opened; - mlx_boolean took_semaphore; - mlx_uint32 max_cmd_size; -} __attribute__ (( packed )) mlx_icmd ; - -typedef struct{ - mlx_pci *pci; - mlx_pci_gw pci_gw; - mlx_icmd icmd; - void *lock; -#ifdef DEVICE_CX3 - /* ACCESS to BAR0 */ - void *config; -#endif -} __attribute__ (( packed )) mlx_utils; - -mlx_status -mlx_utils_init( - IN mlx_utils *utils, - IN mlx_pci *pci - ); - -mlx_status -mlx_utils_teardown( - IN mlx_utils *utils - ); -mlx_status -mlx_utils_delay_in_ms( - IN mlx_uint32 msecs - ); - -mlx_status -mlx_utils_delay_in_us( - IN mlx_uint32 usecs - ); - -mlx_status -mlx_utils_ilog2( - IN mlx_uint32 i, - OUT mlx_uint32 *log - ); - -mlx_status -mlx_utils_init_lock( - IN OUT mlx_utils *utils - ); - -mlx_status -mlx_utils_free_lock( - IN OUT mlx_utils *utils - ); - -mlx_status -mlx_utils_acquire_lock ( - IN OUT mlx_utils *utils - ); - -mlx_status -mlx_utils_release_lock ( - IN OUT mlx_utils *utils - ); - -mlx_status -mlx_utils_rand ( - IN mlx_utils *utils, - OUT mlx_uint32 *rand_num - ); -#endif /* STUB_MLXUTILS_INCLUDE_PUBLIC_MLXUTILS_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_blink_leds/mlx_blink_leds.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_blink_leds/mlx_blink_leds.c deleted file mode 100644 index ba56e72f2..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_blink_leds/mlx_blink_leds.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../mlx_lib/mlx_blink_leds/mlx_blink_leds.h" -#include "../../include/public/mlx_memory.h" -#include "../../include/public/mlx_bail.h" - -mlx_status -mlx_blink_leds( - IN mlx_utils *utils, - IN mlx_uint16 secs - ) -{ - mlx_status status = MLX_SUCCESS; - struct mlx_led_control led_control; - mlx_uint32 reg_status; - - if (utils == NULL ) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - mlx_memory_set(utils, &led_control, 0, sizeof(led_control)); - led_control.beacon_duration = secs; - status = mlx_reg_access(utils, REG_ID_MLCR, REG_ACCESS_WRITE, &led_control, sizeof(led_control), - ®_status); - MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed "); - if (reg_status != 0) { - MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status); - status = MLX_FAILED; - goto reg_err; - } -reg_err: -bad_param: - return status; -} - diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_blink_leds/mlx_blink_leds.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_blink_leds/mlx_blink_leds.h deleted file mode 100644 index 886645fe2..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_blink_leds/mlx_blink_leds.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef MLX_BLINK_LEDS_H_ -#define MLX_BLINK_LEDS_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../mlx_lib/mlx_reg_access/mlx_reg_access.h" -#include "../../include/public/mlx_utils.h" - -struct mlx_led_control { - mlx_uint32 reserved1 :16; - mlx_uint32 port :8; - mlx_uint32 bla :8; -/* -------------- */ - mlx_uint32 beacon_duration :16; - mlx_uint32 reserved2 :16; -/* -------------- */ - mlx_uint32 beacon_remain :16; - mlx_uint32 reserved3 :16; -}; - -mlx_status -mlx_blink_leds( - IN mlx_utils *utils, - IN mlx_uint16 secs - ); - -#endif /* MLX_NVCONFIG_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_link_speed/mlx_link_speed.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_link_speed/mlx_link_speed.c deleted file mode 100644 index d31553024..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_link_speed/mlx_link_speed.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../mlx_lib/mlx_link_speed/mlx_link_speed.h" -#include "../../include/public/mlx_memory.h" -#include "../../include/public/mlx_bail.h" - -mlx_status -mlx_set_link_speed( - IN mlx_utils *utils, - IN mlx_uint8 port_num, - IN LINK_SPEED_TYPE type, - IN LINK_SPEED speed - ) -{ - mlx_status status = MLX_SUCCESS; - struct mlx_link_speed link_speed; - mlx_uint32 reg_status; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - mlx_memory_set(utils, &link_speed, 0, sizeof(link_speed)); - - link_speed.loacl_port = port_num; - link_speed.proto_mask = 1 << type; - - status = mlx_reg_access(utils, REG_ID_PTYS, REG_ACCESS_READ, &link_speed, - sizeof(link_speed), ®_status); - - MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed "); - if (reg_status != 0) { - MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status); - status = MLX_FAILED; - goto reg_err; - } - switch (speed) { - case LINK_SPEED_1GB: - link_speed.eth_proto_admin = link_speed.eth_proto_capability & LINK_SPEED_1GB_MASK; - break; - case LINK_SPEED_10GB: - link_speed.eth_proto_admin = link_speed.eth_proto_capability & LINK_SPEED_10GB_MASK; - break; - case LINK_SPEED_40GB: - link_speed.eth_proto_admin = link_speed.eth_proto_capability & LINK_SPEED_40GB_MASK; - break; - case LINK_SPEED_100GB: - link_speed.eth_proto_admin = link_speed.eth_proto_capability & LINK_SPEED_100GB_MASK; - break; - case LINK_SPEED_SDR: - link_speed.ib_proto_admin = link_speed.ib_proto_capability & LINK_SPEED_SDR_MASK; - break; - case LINK_SPEED_DEFAULT: - if (type == LINK_SPEED_ETH) { - link_speed.eth_proto_admin = link_speed.eth_proto_capability; - } else { - link_speed.ib_proto_admin = link_speed.ib_proto_capability; - } - break; - } - status = mlx_reg_access(utils, REG_ID_PTYS, REG_ACCESS_WRITE, &link_speed, - sizeof(link_speed), ®_status); - MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed "); - if (reg_status != 0) { - MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status); - status = MLX_FAILED; - goto reg_err; - } -reg_err: -bad_param: - return status; -} - -mlx_status -mlx_get_max_speed( - IN mlx_utils *utils, - IN mlx_uint8 port_num, - IN LINK_SPEED_TYPE type, - OUT mlx_uint64 *speed - ) -{ - mlx_status status = MLX_SUCCESS; - struct mlx_link_speed link_speed; - mlx_uint32 reg_status; - mlx_uint64 speed_giga = 0; - mlx_uint8 lanes_number = 1; - - *speed = 0; - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - mlx_memory_set(utils, &link_speed, 0, sizeof(link_speed)); - - link_speed.loacl_port = port_num; - link_speed.proto_mask = 1 << type; - - status = mlx_reg_access(utils, REG_ID_PTYS, REG_ACCESS_READ, &link_speed, - sizeof(link_speed), ®_status); - MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed "); - if (reg_status != 0) { - MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status); - status = MLX_FAILED; - goto reg_err; - } - - if ( type == LINK_SPEED_ETH ) { - if ( link_speed.eth_proto_capability & LINK_SPEED_100GB_MASK ) { - speed_giga = 100; - } else if ( link_speed.eth_proto_capability & LINK_SPEED_56GB_MASK ) { - speed_giga = 56; - } else if ( link_speed.eth_proto_capability & LINK_SPEED_50GB_MASK ) { - speed_giga = 50; - } else if ( link_speed.eth_proto_capability & LINK_SPEED_40GB_MASK ) { - speed_giga = 40; - } else if (link_speed.eth_proto_capability & LINK_SPEED_25GB_MASK) { - speed_giga = 25; - } else if ( link_speed.eth_proto_capability & LINK_SPEED_20GB_MASK ) { - speed_giga = 20; - } else if ( link_speed.eth_proto_capability & LINK_SPEED_10GB_MASK) { - speed_giga = 10; - } else if ( link_speed.eth_proto_capability & LINK_SPEED_1GB_MASK ) { - speed_giga = 1; - } - } else { - if ( link_speed.ib_proto_capability & LINK_SPEED_EDR_MASK ) { - speed_giga = 25; - } else if ( link_speed.ib_proto_capability & LINK_SPEED_EDR20_MASK ) { - speed_giga = 20; - } else if ( link_speed.ib_proto_capability & LINK_SPEED_FDR_MASK ) { - speed_giga = 14; - } else if ( link_speed.ib_proto_capability & LINK_SPEED_QDR_MASK ) { - speed_giga = 10; - } else if ( link_speed.ib_proto_capability & LINK_SPEED_DDR_MASK ) { - speed_giga = 5; - } else if ( link_speed.ib_proto_capability & LINK_SPEED_SDR_MASK ) { - speed_giga = 2.5; - } - if ( link_speed.ib_link_width_capability & LINK_SPEED_WITDH_12_MASK ) { - lanes_number = 12; - } else if ( link_speed.ib_link_width_capability & LINK_SPEED_WITDH_8_MASK ) { - lanes_number = 8; - } else if (link_speed.ib_link_width_capability & LINK_SPEED_WITDH_4_MASK ) { - lanes_number = 4; - } else if (link_speed.ib_link_width_capability & LINK_SPEED_WITDH_2_MASK ) { - lanes_number = 2; - } else if (link_speed.ib_link_width_capability & LINK_SPEED_WITDH_1_MASK ) { - lanes_number = 1; - } - speed_giga = speed_giga * lanes_number; - } - // Return data in bits - *speed = speed_giga * GIGA_TO_BIT; -reg_err: -bad_param: - return status; -} - - diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_link_speed/mlx_link_speed.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_link_speed/mlx_link_speed.h deleted file mode 100644 index 15b28f57a..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_link_speed/mlx_link_speed.h +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef MLX_LINK_SPEED_H_ -#define MLX_LINK_SPEED_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../mlx_lib/mlx_reg_access/mlx_reg_access.h" -#include "../../include/public/mlx_utils.h" - -#define LINK_SPEED_100GB_MASK (ETH_SPEED_ENABLE_MASK_100GBASECR4 | ETH_SPEED_ENABLE_MASK_100GBASESR4 | ETH_SPEED_ENABLE_MASK_100GBASEKR4 | ETH_SPEED_ENABLE_MASK_100GBASELR4) -#define LINK_SPEED_56GB_MASK (ETH_SPEED_ENABLE_MASK_56GBASER4) -#define LINK_SPEED_50GB_MASK (ETH_SPEED_ENABLE_MASK_50GBASECR2 | ETH_SPEED_ENABLE_MASK_50GBASEKR2) -#define LINK_SPEED_40GB_MASK (ETH_SPEED_ENABLE_MASK_40GBASECR4 | ETH_SPEED_ENABLE_MASK_40GBASEKR4 | ETH_SPEED_ENABLE_MASK_40GBASESR4 | ETH_SPEED_ENABLE_MASK_40GBASELR4) -#define LINK_SPEED_25GB_MASK (ETH_SPEED_ENABLE_MASK_25GBASECR | ETH_SPEED_ENABLE_MASK_25GBASEKR | ETH_SPEED_ENABLE_MASK_25GBASESR) -#define LINK_SPEED_20GB_MASK (ETH_SPEED_ENABLE_MASK_20GBASER2) -#define LINK_SPEED_10GB_MASK (ETH_SPEED_ENABLE_MASK_10GBASECR | ETH_SPEED_ENABLE_MASK_10GBASESR | ETH_SPEED_ENABLE_MASK_10GBASELR | ETH_SPEED_ENABLE_MASK_10GBASEKR) -#define LINK_SPEED_1GB_MASK (ETH_SPEED_ENABLE_MASK_1000BASECX | ETH_SPEED_ENABLE_MASK_1000BASEKX | ETH_SPEED_ENABLE_MASK_100BaseTX | ETH_SPEED_ENABLE_MASK_1000BASET) - -#define LINK_SPEED_SDR_MASK 0x1 -#define LINK_SPEED_DDR_MASK 0x2 -#define LINK_SPEED_QDR_MASK 0xC -#define LINK_SPEED_FDR_MASK 0x10 -#define LINK_SPEED_EDR20_MASK 0x200 -#define LINK_SPEED_EDR_MASK 0x20 - -#define LINK_SPEED_WITDH_1_MASK 0x1 -#define LINK_SPEED_WITDH_2_MASK 0x2 -#define LINK_SPEED_WITDH_4_MASK 0x4 -#define LINK_SPEED_WITDH_8_MASK 0x8 -#define LINK_SPEED_WITDH_12_MASK 0x10 - -#define GIGA_TO_BIT 0x40000000 - -enum { - ETH_SPEED_ENABLE_MASK_1000BASECX = 0x0001, - ETH_SPEED_ENABLE_MASK_1000BASEKX = 0x0002, - ETH_SPEED_ENABLE_MASK_10GBASECX4 = 0x0004, - ETH_SPEED_ENABLE_MASK_10GBASEKX4 = 0x0008, - ETH_SPEED_ENABLE_MASK_10GBASEKR = 0x0010, - ETH_SPEED_ENABLE_MASK_20GBASER2 = 0x0020, - ETH_SPEED_ENABLE_MASK_40GBASECR4 = 0x0040, - ETH_SPEED_ENABLE_MASK_40GBASEKR4 = 0x0080, - ETH_SPEED_ENABLE_MASK_56GBASER4 = 0x0100, - ETH_SPEED_ENABLE_MASK_10GBASECR = 0x1000, - ETH_SPEED_ENABLE_MASK_10GBASESR = 0x2000, - ETH_SPEED_ENABLE_MASK_10GBASELR = 0x4000, - ETH_SPEED_ENABLE_MASK_40GBASESR4 = 0x8000, - ETH_SPEED_ENABLE_MASK_40GBASELR4 = 0x10000, - ETH_SPEED_ENABLE_MASK_50GBASEKR4 = 0x80000, - ETH_SPEED_ENABLE_MASK_100GBASECR4 = 0x100000, - ETH_SPEED_ENABLE_MASK_100GBASESR4 = 0x200000, - ETH_SPEED_ENABLE_MASK_100GBASEKR4 = 0x400000, - ETH_SPEED_ENABLE_MASK_100GBASELR4 = 0x800000, - ETH_SPEED_ENABLE_MASK_100BaseTX = 0x1000000, - ETH_SPEED_ENABLE_MASK_1000BASET = 0x2000000, - ETH_SPEED_ENABLE_MASK_10GBASET = 0x4000000, - ETH_SPEED_ENABLE_MASK_25GBASECR = 0x8000000, - ETH_SPEED_ENABLE_MASK_25GBASEKR = 0x10000000, - ETH_SPEED_ENABLE_MASK_25GBASESR = 0x20000000, - ETH_SPEED_ENABLE_MASK_50GBASECR2 = 0x40000000, - ETH_SPEED_ENABLE_MASK_50GBASEKR2 = 0x80000000, - ETH_SPEED_ENABLE_MASK_BAD = 0xffff, -}; - - -typedef enum { - LINK_SPEED_IB = 0, - LINK_SPEED_FC, - LINK_SPEED_ETH, -} LINK_SPEED_TYPE; - -typedef enum { - LINK_SPEED_1GB = 0, - LINK_SPEED_10GB, - LINK_SPEED_40GB, - LINK_SPEED_100GB, - LINK_SPEED_SDR, - LINK_SPEED_DEFAULT, -} LINK_SPEED; - -struct mlx_link_speed { - mlx_uint32 proto_mask :3; - mlx_uint32 reserved1 :13; - mlx_uint32 loacl_port :8; - mlx_uint32 reserved2 :8; - /* -------------- */ - mlx_uint32 reserved3 :32; - /* -------------- */ - mlx_uint32 reserved4 :32; - /* -------------- */ - mlx_uint32 eth_proto_capability :32; - /* -------------- */ - mlx_uint32 ib_proto_capability :16; - mlx_uint32 ib_link_width_capability :16; - /* -------------- */ - mlx_uint32 reserved5 :32; - /* -------------- */ - mlx_uint32 eth_proto_admin :32; - /* -------------- */ - mlx_uint32 ib_proto_admin :16; - mlx_uint32 ib_link_width_admin :16; - /* -------------- */ - mlx_uint32 reserved6 :32; - /* -------------- */ - mlx_uint32 eth_proto_oper :32; - /* -------------- */ - mlx_uint32 ib_proto_oper :16; - mlx_uint32 ib_link_width_oper :16; -}; - -mlx_status -mlx_set_link_speed( - IN mlx_utils *utils, - IN mlx_uint8 port_num, - IN LINK_SPEED_TYPE type, - IN LINK_SPEED speed - ); - -mlx_status -mlx_get_max_speed( - IN mlx_utils *utils, - IN mlx_uint8 port_num, - IN LINK_SPEED_TYPE type, - OUT mlx_uint64 *speed - ); - -#endif /* MLX_LINK_SPEED_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_mtu/mlx_mtu.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_mtu/mlx_mtu.c deleted file mode 100644 index 755730284..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_mtu/mlx_mtu.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_mtu.h" -#include "mlx_memory.h" -#include "mlx_bail.h" - -mlx_status -mlx_get_max_mtu( - IN mlx_utils *utils, - IN mlx_uint8 port_num, - OUT mlx_uint32 *max_mtu - ) -{ - mlx_status status = MLX_SUCCESS; - struct mlx_mtu mtu; - mlx_uint32 reg_status; - *max_mtu = 0; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - mlx_memory_set(utils, &mtu, 0, sizeof(mtu)); - - mtu.local_port = port_num; - - status = mlx_reg_access(utils, REG_ID_PMTU, REG_ACCESS_READ, &mtu, - sizeof(mtu), ®_status); - MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed "); - if (reg_status != 0) { - MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status); - status = MLX_FAILED; - goto reg_err; - } - // Return data in bits - *max_mtu = mtu.max_mtu * BYTE_TO_BIT; -reg_err: -bad_param: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_mtu/mlx_mtu.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_mtu/mlx_mtu.h deleted file mode 100644 index c6222625c..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_mtu/mlx_mtu.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MLX_MTU_H_ -#define MLX_MTU_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_reg_access.h" -#include "mlx_utils.h" - -#define BYTE_TO_BIT 0x8 - -struct mlx_mtu { - mlx_uint32 reserved1 :16; - mlx_uint32 local_port :8; - mlx_uint32 reserved2 :8; - /* -------------- */ - mlx_uint32 reserved3 :16; - mlx_uint32 max_mtu :16; - /* -------------- */ - mlx_uint32 reserved4 :16; - mlx_uint32 admin_mtu :16; - /* -------------- */ - mlx_uint32 reserved5 :16; - mlx_uint32 oper_mtu :16; -}; - -mlx_status -mlx_get_max_mtu( - IN mlx_utils *utils, - IN mlx_uint8 port_num, - OUT mlx_uint32 *max_mtu - ); - -#endif /* MLX_MTU_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig.c deleted file mode 100644 index 2277e0c76..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../mlx_lib/mlx_nvconfig/mlx_nvconfig.h" -#include "../../include/public/mlx_memory.h" -#include "../../include/public/mlx_bail.h" - -#define TlvMappingEntry( _tlv_type, _real_tlv_type, _class_code, _fw_reset_needed) { \ - .tlv_type = _tlv_type, \ - .real_tlv_type = _real_tlv_type, \ - .class_code = _class_code, \ - .fw_reset_needed = _fw_reset_needed, \ - } - -struct nvconfig_tlv_mapping nvconfig_tlv_mapping[] = { - TlvMappingEntry(0x10, 0x10, NVRAM_TLV_CLASS_HOST, TRUE), - TlvMappingEntry(0x12, 0x12, NVRAM_TLV_CLASS_PHYSICAL_PORT, TRUE), - TlvMappingEntry(0x80, 0x80, NVRAM_TLV_CLASS_GLOBAL, TRUE), - TlvMappingEntry(0x81, 0x81, NVRAM_TLV_CLASS_GLOBAL, TRUE), - TlvMappingEntry(0x100, 0x100, NVRAM_TLV_CLASS_GLOBAL, TRUE), - TlvMappingEntry(0x2001, 0x195, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2010, 0x210, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2011, 0x211, NVRAM_TLV_CLASS_GLOBAL, FALSE), - TlvMappingEntry(0x2020, 0x2020, NVRAM_TLV_CLASS_PHYSICAL_PORT, FALSE), - TlvMappingEntry(0x2021, 0x221, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2023, 0x223, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2100, 0x230, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2101, 0x231, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2102, 0x232, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2103, 0x233, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2104, 0x234, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2105, 0x235, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2106, 0x236, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2107, 0x237, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2108, 0x238, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2109, 0x239, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x210A, 0x23A, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2200, 0x240, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2201, 0x241, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2202, 0x242, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2203, 0x243, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2204, 0x244, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2205, 0x245, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0x2207, 0x247, NVRAM_TLV_CLASS_HOST, FALSE), - TlvMappingEntry(0, 0, 0, 0), -}; - -static -mlx_status -nvconfig_set_fw_reset_level( - IN mlx_utils *utils, - IN mlx_uint16 tlv_type - ) -{ -#define WARM_REBOOT_RESET ((mlx_uint64)0x1 << 38) - mlx_status status = MLX_SUCCESS; - mlx_uint32 reg_status; - mlx_uint64 mfrl = WARM_REBOOT_RESET ; - mlx_uint8 index = 0; - mlx_boolean reset_needed = FALSE; - - for (index = 0 ; nvconfig_tlv_mapping[index].tlv_type != 0 ; index++) { - if (nvconfig_tlv_mapping[index].tlv_type == tlv_type) { - reset_needed = nvconfig_tlv_mapping[index].fw_reset_needed; - } - } - - if (reset_needed == FALSE) { - goto no_fw_reset_needed; - } - status = mlx_reg_access(utils, REG_ID_MFRL, REG_ACCESS_WRITE, &mfrl, sizeof(mfrl), - ®_status); - MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed "); - - if (reg_status != 0) { - MLX_DEBUG_ERROR(utils,"nvconfig_set_fw_reset_level failed with status = %d\n", reg_status); - status = MLX_FAILED; - goto reg_err; - } -reg_err: -no_fw_reset_needed: - return status; -} - - -static -mlx_status -nvconfig_get_tlv_type_and_class( - IN mlx_uint16 tlv_type, - OUT mlx_uint16 *real_tlv_type, - OUT NVRAM_CLASS_CODE *class_code - ) -{ - mlx_uint8 index = 0; - for ( ; nvconfig_tlv_mapping[index].tlv_type != 0 ; index ++) { - if ( nvconfig_tlv_mapping[index].tlv_type == tlv_type) { - *real_tlv_type = nvconfig_tlv_mapping[index].real_tlv_type; - *class_code = nvconfig_tlv_mapping[index].class_code; - return MLX_SUCCESS; - } - } - return MLX_NOT_FOUND; -} -static -void -nvconfig_fill_tlv_type( - IN mlx_uint8 port, - IN NVRAM_CLASS_CODE class_code, - IN mlx_uint16 tlv_type, - OUT union nvconfig_tlv_type *nvconfig_tlv_type - ) -{ - switch (class_code) { - case NVRAM_TLV_CLASS_GLOBAL: - nvconfig_tlv_type->global.param_class = NVRAM_TLV_CLASS_GLOBAL; - nvconfig_tlv_type->global.param_idx = tlv_type; - break; - case NVRAM_TLV_CLASS_HOST: - nvconfig_tlv_type->per_host.param_class = NVRAM_TLV_CLASS_HOST; - nvconfig_tlv_type->per_host.param_idx = tlv_type; - break; - case NVRAM_TLV_CLASS_PHYSICAL_PORT: - nvconfig_tlv_type->per_port.param_class = NVRAM_TLV_CLASS_PHYSICAL_PORT; - nvconfig_tlv_type->per_port.param_idx = tlv_type; - nvconfig_tlv_type->per_port.port = port; - break; - } -} -mlx_status -nvconfig_query_capability( - IN mlx_utils *utils, - IN mlx_uint8 port, - IN mlx_uint16 tlv_type, - OUT mlx_boolean *read_supported, - OUT mlx_boolean *write_supported - ) -{ - mlx_status status = MLX_SUCCESS; - struct nvconfig_nvqc nvqc; - mlx_uint32 reg_status; - NVRAM_CLASS_CODE class_code; - mlx_uint16 real_tlv_type; - - if (utils == NULL || read_supported == NULL || write_supported == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = nvconfig_get_tlv_type_and_class(tlv_type, &real_tlv_type, &class_code); - MLX_CHECK_STATUS(utils, status, tlv_not_supported, "tlv not supported"); - - mlx_memory_set(utils, &nvqc, 0, sizeof(nvqc)); - nvconfig_fill_tlv_type(port, class_code, real_tlv_type, &nvqc.tlv_type); - - status = mlx_reg_access(utils, REG_ID_NVQC, REG_ACCESS_READ, &nvqc, sizeof(nvqc), - ®_status); - MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed "); - if (reg_status != 0) { - MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status); - status = MLX_FAILED; - goto reg_err; - } - *read_supported = nvqc.support_rd; - *write_supported = nvqc.support_wr; -reg_err: -tlv_not_supported: -bad_param: - return status; -} - -mlx_status -nvconfig_nvdata_invalidate( - IN mlx_utils *utils, - IN mlx_uint8 port, - IN mlx_uint16 tlv_type - ) -{ - mlx_status status = MLX_SUCCESS; - struct nvconfig_header nv_header; - mlx_uint32 reg_status; - NVRAM_CLASS_CODE class_code; - mlx_uint16 real_tlv_type; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = nvconfig_get_tlv_type_and_class(tlv_type, &real_tlv_type, &class_code); - MLX_CHECK_STATUS(utils, status, tlv_not_supported, "tlv not supported"); - - mlx_memory_set(utils, &nv_header, 0, sizeof(nv_header)); - nvconfig_fill_tlv_type(port, class_code, real_tlv_type, &nv_header.tlv_type); - - status = mlx_reg_access(utils, REG_ID_NVDI, REG_ACCESS_WRITE, &nv_header, sizeof(nv_header), - ®_status); - MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed "); - if (reg_status != 0) { - MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status); - status = MLX_FAILED; - goto reg_err; - } -reg_err: -tlv_not_supported: -bad_param: - return status; -} - -mlx_status -nvconfig_nvdata_access( - IN mlx_utils *utils, - IN mlx_uint8 port, - IN mlx_uint16 tlv_type, - IN REG_ACCESS_OPT opt, - IN mlx_size data_size, - IN NV_DEFAULT_OPT def_en, - IN OUT mlx_uint8 *version, - IN OUT mlx_void *data - ) -{ - mlx_status status = MLX_SUCCESS; - struct nvconfig_nvda nvda; - mlx_uint32 reg_status; - mlx_uint32 real_size_to_read; - mlx_uint32 index; - NVRAM_CLASS_CODE class_code; - mlx_uint16 real_tlv_type; - mlx_size data_size_align_to_dword; - - if (utils == NULL || data == NULL || data_size > NVCONFIG_MAX_TLV_SIZE) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = nvconfig_get_tlv_type_and_class(tlv_type, &real_tlv_type, &class_code); - MLX_CHECK_STATUS(utils, status, tlv_not_supported, "tlv not supported"); - - data_size_align_to_dword = ((data_size + 3) / sizeof(mlx_uint32)) * sizeof(mlx_uint32); - mlx_memory_set(utils, &nvda, 0, sizeof(nvda)); - nvda.nv_header.length = data_size_align_to_dword; - nvda.nv_header.rd_en = 0; - nvda.nv_header.def_en = def_en; - nvda.nv_header.over_en = 1; - nvda.nv_header.version = *version; - - nvconfig_fill_tlv_type(port, class_code, real_tlv_type, &nvda.nv_header.tlv_type); - - mlx_memory_cpy(utils, nvda.data, data, data_size); - for (index = 0 ; index * 4 < NVCONFIG_MAX_TLV_SIZE ; index++) { - mlx_memory_be32_to_cpu(utils,(((mlx_uint32 *)nvda.data)[index]), ((mlx_uint32 *)nvda.data) + index); - } - status = mlx_reg_access(utils, REG_ID_NVDA, opt, &nvda, - data_size_align_to_dword + sizeof(nvda.nv_header), ®_status); - MLX_CHECK_STATUS(utils, status, reg_err, "mlx_reg_access failed "); - if (reg_status != 0) { - MLX_DEBUG_ERROR(utils,"mlx_reg_access failed with status = %d\n", reg_status); - status = MLX_FAILED; - goto reg_err; - } - for (index = 0 ; index * 4 < NVCONFIG_MAX_TLV_SIZE ; index++) { - mlx_memory_cpu_to_be32(utils,(((mlx_uint32 *)nvda.data)[index]), ((mlx_uint32 *)nvda.data) + index); - } - if (opt == REG_ACCESS_READ) { - real_size_to_read = (nvda.nv_header.length > data_size) ? data_size : - nvda.nv_header.length; - mlx_memory_cpy(utils, data, nvda.data, real_size_to_read); - *version = nvda.nv_header.version; - } else { - nvconfig_set_fw_reset_level(utils, tlv_type); - } -reg_err: -tlv_not_supported: -bad_param: - return status; -} - - diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig.h deleted file mode 100644 index 8333e8368..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef MLX_NVCONFIG_H_ -#define MLX_NVCONFIG_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../mlx_reg_access/mlx_reg_access.h" -#include "../../include/public/mlx_utils.h" - -typedef enum { - NVRAM_TLV_CLASS_GLOBAL = 0, - NVRAM_TLV_CLASS_PHYSICAL_PORT = 1, - NVRAM_TLV_CLASS_HOST = 3, -} NVRAM_CLASS_CODE; - -struct nvconfig_tlv_type_per_port { - mlx_uint32 param_idx :16; - mlx_uint32 port :8; - mlx_uint32 param_class :8; -}; - -struct nvconfig_tlv_type_per_host { - mlx_uint32 param_idx :10; - mlx_uint32 function :8; - mlx_uint32 host :6; - mlx_uint32 param_class :8; -}; - -struct nvconfig_tlv_type_global { - mlx_uint32 param_idx :24; - mlx_uint32 param_class :8; -}; - -struct nvconfig_tlv_mapping{ - mlx_uint16 tlv_type; - mlx_uint16 real_tlv_type; - NVRAM_CLASS_CODE class_code; - mlx_boolean fw_reset_needed; -}; - -union nvconfig_tlv_type { - struct nvconfig_tlv_type_per_port per_port; - struct nvconfig_tlv_type_per_host per_host; - struct nvconfig_tlv_type_global global; -}; - - -struct nvconfig_nvqc { - union nvconfig_tlv_type tlv_type; -/* -------------- */ - mlx_uint32 support_rd :1; /*the configuration item is supported and can be read */ - mlx_uint32 support_wr :1; /*the configuration item is supported and can be updated */ - mlx_uint32 reserved1 :2; - mlx_uint32 version :4; /*The maximum version of the configuration item currently supported by the firmware. */ - mlx_uint32 reserved2 :24; -}; - - -struct nvconfig_header { - mlx_uint32 length :9; /*Size of configuration item data in bytes between 0..256 */ - mlx_uint32 reserved0 :3; - mlx_uint32 version :4; /* Configuration item version */ - mlx_uint32 reserved1 :7; - - mlx_uint32 def_en :1; /*Choose whether to access the default value or the user-defined value. - 0x0 Read or write the user-defined value. - 0x1 Read the default value (only valid for reads).*/ - - mlx_uint32 rd_en :1; /*enables reading the TLV by lower priorities - 0 - TLV can be read by the subsequent lifecycle priorities. - 1 - TLV cannot be read by the subsequent lifecycle priorities. */ - mlx_uint32 over_en :1; /*enables overwriting the TLV by lower priorities - 0 - Can only be overwritten by the current lifecycle priority - 1 - Allowed to be overwritten by subsequent lifecycle priorities */ - mlx_uint32 header_type :2; - mlx_uint32 priority :2; - mlx_uint32 valid :2; -/* -------------- */ - union nvconfig_tlv_type tlv_type;; -/* -------------- */ - mlx_uint32 crc :16; - mlx_uint32 reserved :16; -}; - -#define NVCONFIG_MAX_TLV_SIZE 256 - -struct nvconfig_nvda { - struct nvconfig_header nv_header; - mlx_uint8 data[NVCONFIG_MAX_TLV_SIZE]; -}; - - -mlx_status -nvconfig_query_capability( - IN mlx_utils *utils, - IN mlx_uint8 port, - IN mlx_uint16 tlv_type, - OUT mlx_boolean *read_supported, - OUT mlx_boolean *write_supported - ); - - -mlx_status -nvconfig_nvdata_invalidate( - IN mlx_utils *utils, - IN mlx_uint8 port, - IN mlx_uint16 tlv_type - ); - -mlx_status -nvconfig_nvdata_access( - IN mlx_utils *utils, - IN mlx_uint8 port, - IN mlx_uint16 tlv_type, - IN REG_ACCESS_OPT opt, - IN mlx_size data_size, - IN NV_DEFAULT_OPT def_en, - IN OUT mlx_uint8 *version, - IN OUT mlx_void *data - ); - -#endif /* MLX_NVCONFIG_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_defaults.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_defaults.c deleted file mode 100644 index 77eda8a5c..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_defaults.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE( GPL2_OR_LATER); - -#include "../../mlx_lib/mlx_nvconfig/mlx_nvconfig.h" -#include "../../include/public/mlx_memory.h" -#include "../../include/public/mlx_bail.h" -#include "../../mlx_lib/mlx_nvconfig/mlx_nvconfig_defaults.h" - -struct tlv_default { - mlx_uint16 tlv_type; - mlx_size data_size; - mlx_status (*set_defaults)( IN void *data, IN int status, - OUT void *def_struct); -}; - -#define TlvDefaultEntry( _tlv_type, _data_size, _set_defaults) { \ - .tlv_type = _tlv_type, \ - .data_size = sizeof ( _data_size ), \ - .set_defaults = _set_defaults, \ - } - -static -mlx_status -nvconfig_get_boot_default_conf( - IN void *data, - IN int status, - OUT void *def_struct - ) -{ - union mlx_nvconfig_nic_boot_conf *nic_boot_conf = - (union mlx_nvconfig_nic_boot_conf *) data; - struct mlx_nvconfig_port_conf_defaults *port_conf_def = - (struct mlx_nvconfig_port_conf_defaults *) def_struct; - - /* boot_option_rom_en is deprecated - enabled always */ - port_conf_def->boot_option_rom_en = DEFAULT_OPTION_ROM_EN; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "TLV not found. Using hard-coded defaults "); - port_conf_def->boot_vlan = nic_boot_conf->vlan_id; - port_conf_def->boot_protocol = nic_boot_conf->legacy_boot_prot; - port_conf_def->boot_retry_count = nic_boot_conf->boot_retry_count; - port_conf_def->boot_vlan_en = nic_boot_conf->en_vlan; - - return MLX_SUCCESS; - -nvdata_access_err: - port_conf_def->boot_vlan = DEFAULT_BOOT_VLAN; - port_conf_def->boot_protocol = DEFAULT_BOOT_PROTOCOL; - - return status; -} - -static -mlx_status -nvconfig_get_boot_ext_default_conf( - IN void *data, - IN int status, - OUT void *def_struct - ) -{ - union mlx_nvconfig_nic_boot_ext_conf *nic_boot_ext_conf = - (union mlx_nvconfig_nic_boot_ext_conf *) data; - struct mlx_nvconfig_port_conf_defaults *port_conf_def = - (struct mlx_nvconfig_port_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "TLV not found. Using hard-coded defaults "); - port_conf_def->linkup_timeout = nic_boot_ext_conf->linkup_timeout; - port_conf_def->ip_ver = nic_boot_ext_conf->ip_ver; - - return MLX_SUCCESS; - -nvdata_access_err: - port_conf_def->linkup_timeout = DEFAULT_BOOT_LINK_UP_TO; - port_conf_def->ip_ver = DEFAULT_BOOT_IP_VER; - - return status; -} - -static -mlx_status -nvconfig_get_iscsi_init_dhcp_default_conf( - IN void *data, - IN int status, - OUT void *def_struct - ) -{ - union mlx_nvconfig_iscsi_init_dhcp_conf *iscsi_init_dhcp_conf = - (union mlx_nvconfig_iscsi_init_dhcp_conf *) data; - struct mlx_nvconfig_port_conf_defaults *port_conf_def = - (struct mlx_nvconfig_port_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "TLV not found. Using hard-coded defaults "); - port_conf_def->iscsi_dhcp_params_en = iscsi_init_dhcp_conf->dhcp_iscsi_en; - port_conf_def->iscsi_ipv4_dhcp_en = iscsi_init_dhcp_conf->ipv4_dhcp_en; - - return MLX_SUCCESS; - -nvdata_access_err: - port_conf_def->iscsi_dhcp_params_en = DEFAULT_ISCSI_DHCP_PARAM_EN; - port_conf_def->iscsi_ipv4_dhcp_en = DEFAULT_ISCSI_IPV4_DHCP_EN; - - return status; -} - -static -mlx_status -nvconfig_get_ib_boot_default_conf( - IN void *data, - IN int status, - OUT void *def_struct - ) -{ - union mlx_nvconfig_nic_ib_boot_conf *ib_boot_conf = - (union mlx_nvconfig_nic_ib_boot_conf *) data; - struct mlx_nvconfig_port_conf_defaults *port_conf_def = - (struct mlx_nvconfig_port_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "nvconfig_nvdata_default_access failed "); - port_conf_def->boot_pkey = ib_boot_conf->boot_pkey; - -nvdata_access_err: - return status; -} - -static -mlx_status -nvconfig_get_wol_default_conf( - IN void *data, - IN int status, - OUT void *def_struct - ) -{ - union mlx_nvconfig_wol_conf *wol_conf = (union mlx_nvconfig_wol_conf *) data; - struct mlx_nvconfig_port_conf_defaults *port_conf_def = - (struct mlx_nvconfig_port_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "nvconfig_nvdata_default_access failed "); - port_conf_def->en_wol_magic = wol_conf->en_wol_magic; - -nvdata_access_err: - return status; -} - -static -mlx_status -nvconfig_get_iscsi_gen_default_conf( - IN void *data, - IN int status, - OUT void *def_struct) -{ - union mlx_nvconfig_iscsi_general *iscsi_gen = - (union mlx_nvconfig_iscsi_general *) data; - struct mlx_nvconfig_port_conf_defaults *port_conf_def = - (struct mlx_nvconfig_port_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "nvconfig_nvdata_default_access failed "); - port_conf_def->iscsi_boot_to_target = iscsi_gen->boot_to_target; - port_conf_def->iscsi_vlan_en = iscsi_gen->vlan_en; - port_conf_def->iscsi_tcp_timestamps_en = iscsi_gen->tcp_timestamps_en; - port_conf_def->iscsi_chap_mutual_auth_en = iscsi_gen->chap_mutual_auth_en; - port_conf_def->iscsi_chap_auth_en = iscsi_gen->chap_auth_en; - port_conf_def->iscsi_lun_busy_retry_count = iscsi_gen->lun_busy_retry_count; - port_conf_def->iscsi_link_up_delay_time = iscsi_gen->link_up_delay_time; - -nvdata_access_err: - return status; -} - -static -mlx_status -nvconfig_get_ib_dhcp_default_conf( - IN void *data, - IN int status, - OUT void *def_struct - ) -{ - union mlx_nvconfig_ib_dhcp_conf *ib_dhcp = - (union mlx_nvconfig_ib_dhcp_conf *) data; - struct mlx_nvconfig_port_conf_defaults *port_conf_def = - (struct mlx_nvconfig_port_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "nvconfig_nvdata_default_access failed "); - port_conf_def->client_identifier = ib_dhcp->client_identifier; - port_conf_def->mac_admin_bit = ib_dhcp->mac_admin_bit; - -nvdata_access_err: - return status; -} - -static -mlx_status -nvconfig_get_ocsd_ocbb_default_conf( IN void *data, - IN int status, OUT void *def_struct) { - union mlx_nvconfig_ocsd_ocbb_conf *ocsd_ocbb = - (union mlx_nvconfig_ocsd_ocbb_conf *) data; - struct mlx_nvconfig_conf_defaults *conf_def = - (struct mlx_nvconfig_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "TLV not found. Using hard-coded defaults "); - conf_def->ocsd_ocbb_en = ocsd_ocbb->ocsd_ocbb_en; - - return MLX_SUCCESS; - -nvdata_access_err: - conf_def->ocsd_ocbb_en = DEFAULT_OCSD_OCBB_EN; - - return status; -} - -static -mlx_status -nvconfig_get_vpi_link_default_conf( - IN void *data, - IN int status, - OUT void *def_struct - ) -{ - union mlx_nvconfig_vpi_link_conf *vpi_link = - (union mlx_nvconfig_vpi_link_conf *) data; - struct mlx_nvconfig_port_conf_defaults *port_conf_def = - (struct mlx_nvconfig_port_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "nvconfig_nvdata_default_access failed "); - port_conf_def->network_link_type = vpi_link->network_link_type; - port_conf_def->default_link_type = vpi_link->default_link_type; - -nvdata_access_err: - return status; -} - -static -mlx_status -nvconfig_get_rom_banner_to_default_conf( - IN void *data, - IN int status, - OUT void *def_struct - ) -{ - union mlx_nvconfig_rom_banner_timeout_conf *rom_banner_timeout_conf = - (union mlx_nvconfig_rom_banner_timeout_conf *) data; - struct mlx_nvconfig_conf_defaults *conf_def = - (struct mlx_nvconfig_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "TLV not found. Using hard-coded defaults "); - conf_def->flexboot_menu_to = rom_banner_timeout_conf->rom_banner_to; - - return MLX_SUCCESS; - -nvdata_access_err: - conf_def->flexboot_menu_to = DEFAULT_FLEXBOOT_MENU_TO; - - return status; -} - -static -mlx_status -nvconfig_get_nv_virt_caps_default_conf( - IN void *data, - IN int status, - OUT void *def_struct - ) -{ - union mlx_nvconfig_virt_caps *nv_virt_caps = - (union mlx_nvconfig_virt_caps *) data; - struct mlx_nvconfig_conf_defaults *conf_def = - (struct mlx_nvconfig_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "TLV not found. Using hard-coded defaults "); - conf_def->max_vfs = nv_virt_caps->max_vfs_per_pf; - - return MLX_SUCCESS; - -nvdata_access_err: - conf_def->max_vfs = DEFAULT_MAX_VFS; - - return status; -} - -static -mlx_status -nvconfig_get_nv_virt_default_conf( - IN void *data, - IN int status, - OUT void *def_struct - ) -{ - union mlx_nvconfig_virt_conf *nv_virt_conf = - (union mlx_nvconfig_virt_conf *) data; - struct mlx_nvconfig_conf_defaults *conf_def = - (struct mlx_nvconfig_conf_defaults *) def_struct; - - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "nvconfig_nvdata_default_access failed "); - conf_def->total_vfs = nv_virt_conf->num_of_vfs; - conf_def->sriov_en = nv_virt_conf->virt_mode; - -nvdata_access_err: - return status; -} - -static struct tlv_default tlv_port_defaults[] = { - TlvDefaultEntry(BOOT_SETTINGS_TYPE, union mlx_nvconfig_nic_boot_conf, &nvconfig_get_boot_default_conf), - TlvDefaultEntry(BOOT_SETTINGS_EXT_TYPE, union mlx_nvconfig_nic_boot_ext_conf, &nvconfig_get_boot_ext_default_conf), - TlvDefaultEntry(ISCSI_INITIATOR_DHCP_CONF_TYPE, union mlx_nvconfig_iscsi_init_dhcp_conf, &nvconfig_get_iscsi_init_dhcp_default_conf), - TlvDefaultEntry(IB_BOOT_SETTING_TYPE, union mlx_nvconfig_nic_ib_boot_conf, &nvconfig_get_ib_boot_default_conf), - TlvDefaultEntry(WAKE_ON_LAN_TYPE, union mlx_nvconfig_wol_conf, &nvconfig_get_wol_default_conf), - TlvDefaultEntry(ISCSI_GENERAL_SETTINGS_TYPE, union mlx_nvconfig_iscsi_general, &nvconfig_get_iscsi_gen_default_conf), - TlvDefaultEntry(IB_DHCP_SETTINGS_TYPE, union mlx_nvconfig_ib_dhcp_conf, &nvconfig_get_ib_dhcp_default_conf), - TlvDefaultEntry(VPI_LINK_TYPE, union mlx_nvconfig_vpi_link_conf, &nvconfig_get_vpi_link_default_conf), -}; - -static struct tlv_default tlv_general_defaults[] = { - TlvDefaultEntry(BANNER_TO_TYPE, union mlx_nvconfig_rom_banner_timeout_conf, &nvconfig_get_rom_banner_to_default_conf), - TlvDefaultEntry(GLOPAL_PCI_CAPS_TYPE, union mlx_nvconfig_virt_caps, &nvconfig_get_nv_virt_caps_default_conf), - TlvDefaultEntry(GLOPAL_PCI_SETTINGS_TYPE, union mlx_nvconfig_virt_conf, &nvconfig_get_nv_virt_default_conf), - TlvDefaultEntry(OCSD_OCBB_TYPE, union mlx_nvconfig_ocsd_ocbb_conf, &nvconfig_get_ocsd_ocbb_default_conf), -}; - -static -mlx_status -nvconfig_nvdata_default_access( - IN mlx_utils *utils, - IN mlx_uint8 port, - IN mlx_uint16 tlv_type, - IN mlx_size data_size, - OUT mlx_void *data - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 index; - mlx_uint8 version = 0; - - status = nvconfig_nvdata_access(utils, port, tlv_type, REG_ACCESS_READ, - data_size, TLV_ACCESS_DEFAULT_EN, &version, data); - MLX_CHECK_STATUS(NULL, status, nvdata_access_err, - "nvconfig_nvdata_access failed "); - for (index = 0; index * 4 < data_size; index++) { - mlx_memory_be32_to_cpu(utils, (((mlx_uint32 *) data)[index]), - ((mlx_uint32 *) data) + index); - } - -nvdata_access_err: - return status; -} - -static -mlx_status -nvconfig_nvdata_read_default_value( - IN mlx_utils *utils, - IN mlx_uint8 modifier, - IN struct tlv_default *def, - OUT void *def_struct - ) -{ - mlx_status status = MLX_SUCCESS; - void *data = NULL; - - status = mlx_memory_zalloc(utils, def->data_size,&data); - MLX_CHECK_STATUS(utils, status, memory_err, - "mlx_memory_zalloc failed "); - status = nvconfig_nvdata_default_access(utils, modifier, def->tlv_type, - def->data_size, data); - def->set_defaults(data, status, def_struct); - mlx_memory_free(utils, &data); - -memory_err: - return status; -} - -static -void -nvconfig_nvdata_read_default_values( - IN mlx_utils *utils, - IN mlx_uint8 modifier, - IN struct tlv_default defaults_table[], - IN mlx_uint8 defaults_table_size, - OUT void *def_strct - ) -{ - struct tlv_default *defs; - unsigned int i; - - for (i = 0; i < defaults_table_size; i++) { - defs = &defaults_table[i]; - nvconfig_nvdata_read_default_value(utils, modifier, defs, def_strct); - } -} - -mlx_status -nvconfig_read_port_default_values( - IN mlx_utils *utils, - IN mlx_uint8 port, - OUT struct mlx_nvconfig_port_conf_defaults *port_conf_def - ) -{ - mlx_status status = MLX_SUCCESS; - - if (utils == NULL || port_conf_def == NULL) { - status = MLX_INVALID_PARAMETER; - MLX_DEBUG_ERROR(utils,"bad params."); - goto bad_param; - } - mlx_memory_set(utils, port_conf_def, 0, sizeof(*port_conf_def)); - nvconfig_nvdata_read_default_values(utils, port, tlv_port_defaults, - (sizeof(tlv_port_defaults)/sizeof(tlv_port_defaults[0])), - port_conf_def); - -bad_param: - return status; -} - -mlx_status -nvconfig_read_general_default_values( - IN mlx_utils *utils, - OUT struct mlx_nvconfig_conf_defaults *conf_def - ) -{ - mlx_status status = MLX_SUCCESS; - - if (utils == NULL || conf_def == NULL) { - status = MLX_INVALID_PARAMETER; - MLX_DEBUG_ERROR(utils,"bad params."); - goto bad_param; - } - mlx_memory_set(utils, conf_def, 0, sizeof(*conf_def)); - nvconfig_nvdata_read_default_values(utils, 0, tlv_general_defaults, - (sizeof(tlv_general_defaults)/sizeof(tlv_general_defaults[0])), - conf_def); - -bad_param: - return status; -} - -mlx_status -nvconfig_read_rom_ini_values( - IN mlx_utils *utils, - OUT struct mlx_nvcofnig_romini *rom_ini - ) -{ - mlx_status status = MLX_SUCCESS; - - if (utils == NULL || rom_ini == NULL) { - status = MLX_INVALID_PARAMETER; - MLX_DEBUG_ERROR(utils,"bad params."); - goto bad_param; - } - mlx_memory_set(utils, rom_ini, 0, sizeof(*rom_ini)); - - status = nvconfig_nvdata_default_access(utils, 0, GLOBAL_ROM_INI_TYPE, - sizeof(*rom_ini), rom_ini); -bad_param: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_defaults.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_defaults.h deleted file mode 100644 index 163c2a35f..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_defaults.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef MLX_NVCONFIG_DEFAULTS_H_ -#define MLX_NVCONFIG_DEFAULTS_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); -#include "mlx_nvconfig_prm.h" -/* - * Default values - */ -#define DEFAULT_FLEXBOOT_MENU_TO 4 -#define DEFAULT_MAX_VFS 8 -#define DEFAULT_BOOT_PROTOCOL 1 -#define DEFAULT_OPTION_ROM_EN 1 -#define DEFAULT_BOOT_VLAN 1 -#define DEFAULT_ISCSI_DHCP_PARAM_EN 1 -#define DEFAULT_ISCSI_IPV4_DHCP_EN 1 -#define DEFAULT_OCSD_OCBB_EN 1 -#define DEFAULT_BOOT_IP_VER 0 -#define DEFAULT_BOOT_LINK_UP_TO 0 - -struct mlx_nvconfig_port_conf_defaults { - mlx_uint8 pptx; - mlx_uint8 pprx; - mlx_boolean boot_option_rom_en; - mlx_boolean boot_vlan_en; - mlx_uint8 boot_retry_count; - mlx_uint8 boot_protocol; - mlx_uint8 boot_vlan; - mlx_uint8 boot_pkey; - mlx_boolean en_wol_magic; - mlx_uint8 network_link_type; - mlx_uint8 iscsi_boot_to_target; - mlx_boolean iscsi_vlan_en; - mlx_boolean iscsi_tcp_timestamps_en; - mlx_boolean iscsi_chap_mutual_auth_en; - mlx_boolean iscsi_chap_auth_en; - mlx_boolean iscsi_dhcp_params_en; - mlx_boolean iscsi_ipv4_dhcp_en; - mlx_uint8 iscsi_lun_busy_retry_count; - mlx_uint8 iscsi_link_up_delay_time; - mlx_uint8 client_identifier; - mlx_uint8 mac_admin_bit; - mlx_uint8 default_link_type; - mlx_uint8 linkup_timeout; - mlx_uint8 ip_ver; -}; - -struct mlx_nvconfig_conf_defaults { - mlx_uint8 max_vfs; - mlx_uint8 total_vfs; - mlx_uint8 sriov_en; - mlx_uint8 maximum_uar_bar_size; - mlx_uint8 uar_bar_size; - mlx_uint8 flexboot_menu_to; - mlx_boolean ocsd_ocbb_en; -}; - -mlx_status -nvconfig_read_port_default_values( - IN mlx_utils *utils, - IN mlx_uint8 port, - OUT struct mlx_nvconfig_port_conf_defaults *port_conf_def - ); - -mlx_status -nvconfig_read_general_default_values( - IN mlx_utils *utils, - OUT struct mlx_nvconfig_conf_defaults *conf_def - ); - -mlx_status -nvconfig_read_rom_ini_values( - IN mlx_utils *utils, - OUT struct mlx_nvcofnig_romini *rom_ini - ); -#endif /* MLX_NVCONFIG_DEFAULTS_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_prm.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_prm.h deleted file mode 100644 index 5b3af1e78..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_nvconfig/mlx_nvconfig_prm.h +++ /dev/null @@ -1,259 +0,0 @@ -#ifndef MLX_NVCONFIG_PRM_H_ -#define MLX_NVCONFIG_PRM_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../include/public/mlx_types.h" - -enum { - WAKE_ON_LAN_TYPE = 0x10, - VIRTUALIZATION_TYPE = 0x11, - VPI_LINK_TYPE = 0x12, - BOOT_SETTINGS_EXT_TYPE = 0x2001, - BANNER_TO_TYPE = 0x2010, - OCSD_OCBB_TYPE = 0x2011, - FLOW_CONTROL_TYPE = 0x2020, - BOOT_SETTINGS_TYPE = 0x2021, - ISCSI_GENERAL_SETTINGS_TYPE = 0x2100, - IB_BOOT_SETTING_TYPE = 0x2022, - IB_DHCP_SETTINGS_TYPE = 0x2023, - GLOPAL_PCI_SETTINGS_TYPE = 0x80, - GLOPAL_PCI_CAPS_TYPE = 0x81, - GLOBAL_ROM_INI_TYPE = 0x100, - - // Types for iSCSI strings - DHCP_VEND_ID = 0x2101, - ISCSI_INITIATOR_IPV4_ADDR = 0x2102, - ISCSI_INITIATOR_SUBNET = 0x2103, - ISCSI_INITIATOR_IPV4_GATEWAY = 0x2104, - ISCSI_INITIATOR_IPV4_PRIM_DNS = 0x2105, - ISCSI_INITIATOR_IPV4_SECDNS = 0x2106, - ISCSI_INITIATOR_NAME = 0x2107, - ISCSI_INITIATOR_CHAP_ID = 0x2108, - ISCSI_INITIATOR_CHAP_PWD = 0x2109, - ISCSI_INITIATOR_DHCP_CONF_TYPE = 0x210a, - - CONNECT_FIRST_TGT = 0x2200, - FIRST_TGT_IP_ADDRESS = 0x2201, - FIRST_TGT_TCP_PORT = 0x2202, - FIRST_TGT_BOOT_LUN = 0x2203, - FIRST_TGT_ISCSI_NAME = 0x2204, - FIRST_TGT_CHAP_ID = 0x2205, - FIRST_TGT_CHAP_PWD = 0x2207, -}; - -union mlx_nvconfig_nic_boot_conf { - struct { - mlx_uint32 vlan_id : 12; - mlx_uint32 link_speed : 4; - mlx_uint32 legacy_boot_prot : 8; - mlx_uint32 boot_retry_count : 3; - mlx_uint32 boot_strap_type : 3; - mlx_uint32 en_vlan : 1; - mlx_uint32 en_option_rom : 1; - }; - mlx_uint32 dword; -}; - -union mlx_nvconfig_nic_boot_ext_conf { - struct { - mlx_uint32 linkup_timeout : 8; - mlx_uint32 ip_ver : 2; - mlx_uint32 reserved0 : 22; - }; - mlx_uint32 dword; -}; - -union mlx_nvconfig_rom_banner_timeout_conf { - struct { - mlx_uint32 rom_banner_to : 4; - mlx_uint32 reserved : 28; - }; - mlx_uint32 dword; -}; - -union mlx_nvconfig_virt_conf { - struct { - mlx_uint32 reserved0 :24; - mlx_uint32 pf_bar_size_valid :1; - mlx_uint32 vf_bar_size_valid :1; - mlx_uint32 num_pf_msix_valid :1; - mlx_uint32 num_vf_msix_valid :1; - mlx_uint32 num_pfs_valid :1; - mlx_uint32 fpp_valid :1; - mlx_uint32 full_vf_qos_valid :1; - mlx_uint32 sriov_valid :1; - /*-------------------*/ - mlx_uint32 num_of_vfs :16; - mlx_uint32 num_of_pfs :4; - mlx_uint32 reserved1 :9; - mlx_uint32 fpp_en :1; - mlx_uint32 full_vf_qos :1; - mlx_uint32 virt_mode :1; //sriov_en - /*-------------------*/ - mlx_uint32 log_pf_uar_bar_size :6; - mlx_uint32 log_vf_uar_bar_size :6; - mlx_uint32 num_pf_msix :10; - mlx_uint32 num_vf_msix :10; - }; - mlx_uint32 dword[3]; -}; - -union mlx_nvconfig_virt_caps { - struct { - mlx_uint32 reserved0 :24; - mlx_uint32 max_vfs_per_pf_valid :1; - mlx_uint32 max_total_msix_valid :1; - mlx_uint32 max_total_bar_valid :1; - mlx_uint32 num_pfs_supported :1; - mlx_uint32 num_vf_msix_supported :1; - mlx_uint32 num_pf_msix_supported :1; - mlx_uint32 vf_bar_size_supported :1; - mlx_uint32 pf_bar_size_supported :1; - /*-------------------*/ - mlx_uint32 max_vfs_per_pf :16; - mlx_uint32 max_num_pfs :4; - mlx_uint32 reserved1 :9; - mlx_uint32 fpp_support :1; - mlx_uint32 vf_qos_control_support :1; - mlx_uint32 sriov_support :1; - /*-------------------*/ - mlx_uint32 max_log_pf_uar_bar_size :6; - mlx_uint32 max_log_vf_uar_bar_size :6; - mlx_uint32 max_num_pf_msix :10; - mlx_uint32 max_num_vf_msix :10; - /*-------------------*/ - mlx_uint32 max_total_msix; - /*-------------------*/ - mlx_uint32 max_total_bar; - }; - mlx_uint32 dword[5]; -}; - -union mlx_nvconfig_iscsi_init_dhcp_conf { - struct { - mlx_uint32 reserved0 :30; - mlx_uint32 dhcp_iscsi_en :1; - mlx_uint32 ipv4_dhcp_en :1; - - }; - mlx_uint32 dword; -}; - -union mlx_nvconfig_nic_ib_boot_conf { - struct { - mlx_uint32 boot_pkey : 16; - mlx_uint32 reserved0 : 16; - }; - mlx_uint32 dword; -}; - -union mlx_nvconfig_wol_conf { - struct { - mlx_uint32 reserved0 :9; - mlx_uint32 en_wol_passwd :1; - mlx_uint32 en_wol_magic :1; - mlx_uint32 reserved1 :21; - mlx_uint32 reserved2 :32; - }; - mlx_uint32 dword[2]; -}; - -union mlx_nvconfig_iscsi_general { - struct { - mlx_uint32 reserved0 :22; - mlx_uint32 boot_to_target :2; - mlx_uint32 reserved1 :2; - mlx_uint32 vlan_en :1; - mlx_uint32 tcp_timestamps_en :1; - mlx_uint32 chap_mutual_auth_en :1; - mlx_uint32 chap_auth_en :1; - mlx_uint32 reserved2 :2; - /*-------------------*/ - mlx_uint32 vlan :12; - mlx_uint32 reserved3 :20; - /*-------------------*/ - mlx_uint32 lun_busy_retry_count:8; - mlx_uint32 link_up_delay_time :8; - mlx_uint32 reserved4 :16; - }; - mlx_uint32 dword[3]; -}; - -union mlx_nvconfig_ib_dhcp_conf { - struct { - mlx_uint32 reserved :24; - mlx_uint32 client_identifier :4; - mlx_uint32 mac_admin_bit :4; - }; - mlx_uint32 dword; -}; - -union mlx_nvconfig_ocsd_ocbb_conf { - struct { - mlx_uint32 reserved :31; - mlx_uint32 ocsd_ocbb_en :1; - }; - mlx_uint32 dword; -}; - -union mlx_nvconfig_vpi_link_conf { - struct { - mlx_uint32 network_link_type :2; - mlx_uint32 default_link_type :2; - mlx_uint32 reserved :28; - }; - mlx_uint32 dword; -}; - -struct mlx_nvcofnig_romini { - mlx_uint32 reserved0 :1; - mlx_uint32 shared_memory_en :1; - mlx_uint32 hii_vpi_en :1; - mlx_uint32 tech_enum :1; - mlx_uint32 reserved1 :4; - mlx_uint32 static_component_name_string :1; - mlx_uint32 hii_iscsi_configuration :1; - mlx_uint32 hii_ibm_aim :1; - mlx_uint32 hii_platform_setup :1; - mlx_uint32 hii_bdf_decimal :1; - mlx_uint32 hii_read_only :1; - mlx_uint32 reserved2 :10; - mlx_uint32 mac_enum :1; - mlx_uint32 port_enum :1; - mlx_uint32 flash_en :1; - mlx_uint32 fmp_en :1; - mlx_uint32 bofm_en :1; - mlx_uint32 platform_to_driver_en :1; - mlx_uint32 hii_en :1; - mlx_uint32 undi_en :1; - /* -------------- */ - mlx_uint64 dhcp_user_class; - /* -------------- */ - mlx_uint32 reserved3 :22; - mlx_uint32 uri_boot_retry_delay :4; - mlx_uint32 uri_boot_retry :4; - mlx_uint32 option_rom_debug :1; - mlx_uint32 promiscuous_vlan :1; -}; - -#endif /* MLX_NVCONFIG_PRM_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_ocbb/mlx_ocbb.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_ocbb/mlx_ocbb.c deleted file mode 100644 index 3852efbf1..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_ocbb/mlx_ocbb.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_ocbb.h" -#include "mlx_icmd.h" -#include "mlx_bail.h" - -mlx_status -mlx_ocbb_init ( - IN mlx_utils *utils, - IN mlx_uint64 address - ) -{ - mlx_status status = MLX_SUCCESS; - struct mlx_ocbb_init ocbb_init; - ocbb_init.address_hi = (mlx_uint32)(address >> 32); - ocbb_init.address_lo = (mlx_uint32)address; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = mlx_icmd_send_command( - utils, - OCBB_INIT, - &ocbb_init, - sizeof(ocbb_init), - 0 - ); - MLX_CHECK_STATUS(utils, status, icmd_err, "mlx_icmd_send_command failed"); -icmd_err: -bad_param: - return status; -} - -mlx_status -mlx_ocbb_query_header_status ( - IN mlx_utils *utils, - OUT mlx_uint8 *ocbb_status - ) -{ - mlx_status status = MLX_SUCCESS; - struct mlx_ocbb_query_status ocbb_query_status; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = mlx_icmd_send_command( - utils, - OCBB_QUERY_HEADER_STATUS, - &ocbb_query_status, - 0, - sizeof(ocbb_query_status) - ); - MLX_CHECK_STATUS(utils, status, icmd_err, "mlx_icmd_send_command failed"); - *ocbb_status = ocbb_query_status.status; -icmd_err: -bad_param: - return status; -} - -mlx_status -mlx_ocbb_query_etoc_status ( - IN mlx_utils *utils, - OUT mlx_uint8 *ocbb_status - ) -{ - mlx_status status = MLX_SUCCESS; - struct mlx_ocbb_query_status ocbb_query_status; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = mlx_icmd_send_command( - utils, - OCBB_QUERY_ETOC_STATUS, - &ocbb_query_status, - 0, - sizeof(ocbb_query_status) - ); - MLX_CHECK_STATUS(utils, status, icmd_err, "mlx_icmd_send_command failed"); - *ocbb_status = ocbb_query_status.status; -icmd_err: -bad_param: - return status; -} - -mlx_status -mlx_ocbb_set_event ( - IN mlx_utils *utils, - IN mlx_uint64 event_data, - IN mlx_uint8 event_number, - IN mlx_uint8 event_length, - IN mlx_uint8 data_length, - IN mlx_uint8 data_start_offset - ) -{ - mlx_status status = MLX_SUCCESS; - struct mlx_ocbb_set_event ocbb_event; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - ocbb_event.data_length = data_length; - ocbb_event.data_start_offset = data_start_offset; - ocbb_event.event_number = event_number; - ocbb_event.event_data = event_data; - ocbb_event.event_length = event_length; - status = mlx_icmd_send_command( - utils, - OCBB_QUERY_SET_EVENT, - &ocbb_event, - sizeof(ocbb_event), - 0 - ); - MLX_CHECK_STATUS(utils, status, icmd_err, "mlx_icmd_send_command failed"); -icmd_err: -bad_param: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_ocbb/mlx_ocbb.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_ocbb/mlx_ocbb.h deleted file mode 100644 index 49312b98f..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_ocbb/mlx_ocbb.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef MLX_OCBB_H_ -#define MLX_OCBB_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_utils.h" - -#define MLX_OCBB_EVENT_DATA_SIZE 2 -struct mlx_ocbb_init { - mlx_uint32 address_hi; - mlx_uint32 address_lo; -}; - -struct mlx_ocbb_query_status { - mlx_uint32 reserved :24; - mlx_uint32 status :8; -}; - -struct mlx_ocbb_set_event { - mlx_uint64 event_data; - mlx_uint32 event_number :8; - mlx_uint32 event_length :8; - mlx_uint32 data_length :8; - mlx_uint32 data_start_offset :8; -}; - -mlx_status -mlx_ocbb_init ( - IN mlx_utils *utils, - IN mlx_uint64 address - ); - -mlx_status -mlx_ocbb_query_header_status ( - IN mlx_utils *utils, - OUT mlx_uint8 *ocbb_status - ); - -mlx_status -mlx_ocbb_query_etoc_status ( - IN mlx_utils *utils, - OUT mlx_uint8 *ocbb_status - ); - -mlx_status -mlx_ocbb_set_event ( - IN mlx_utils *utils, - IN mlx_uint64 EventData, - IN mlx_uint8 EventNumber, - IN mlx_uint8 EventLength, - IN mlx_uint8 DataLength, - IN mlx_uint8 DataStartOffset - ); -#endif /* MLX_OCBB_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_reg_access/mlx_reg_access.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_reg_access/mlx_reg_access.c deleted file mode 100644 index 143ab1b0e..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_reg_access/mlx_reg_access.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../mlx_lib/mlx_reg_access/mlx_reg_access.h" -#include "../../include/public/mlx_icmd.h" -#include "../../include/public/mlx_bail.h" -#include "../../include/public/mlx_memory.h" - -static -mlx_status -init_operation_tlv( - IN struct mail_box_tlv *mail_box_tlv, - IN mlx_uint16 reg_id, - IN REG_ACCESS_OPT reg_opt - ) -{ -#define TLV_OPERATION 1 - mail_box_tlv->operation_tlv.Type = TLV_OPERATION; -#define MAD_CLASS_REG_ACCESS 1 - mail_box_tlv->operation_tlv.cls = MAD_CLASS_REG_ACCESS; -#define TLV_OPERATION_SIZE 4 - mail_box_tlv->operation_tlv.len = TLV_OPERATION_SIZE; - mail_box_tlv->operation_tlv.method = reg_opt; - mail_box_tlv->operation_tlv.register_id = reg_id; - return MLX_SUCCESS; -} - -mlx_status -mlx_reg_access( - IN mlx_utils *utils, - IN mlx_uint16 reg_id, - IN REG_ACCESS_OPT reg_opt, - IN OUT mlx_void *reg_data, - IN mlx_size reg_size, - OUT mlx_uint32 *reg_status - ) -{ - mlx_status status = MLX_SUCCESS; - struct mail_box_tlv mail_box_tlv; - - if (utils == NULL || reg_data == NULL || reg_status == NULL - || reg_size > REG_ACCESS_MAX_REG_SIZE) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - mlx_memory_set(utils, &mail_box_tlv, 0, sizeof(mail_box_tlv)); - - init_operation_tlv(&mail_box_tlv, reg_id, reg_opt); - -#define REG_ACCESS_TLV_REG 3 -#define REG_TLV_HEADER_LEN 4 -#define OP_TLV_SIZE 16 - mail_box_tlv.reg_tlv.Type = REG_ACCESS_TLV_REG; - mail_box_tlv.reg_tlv.len = ((reg_size + REG_TLV_HEADER_LEN + 3) >> 2); // length is in dwords round up - mlx_memory_cpy(utils, &mail_box_tlv.reg_tlv.data, reg_data, reg_size); - - reg_size += OP_TLV_SIZE + REG_TLV_HEADER_LEN; - - status = mlx_icmd_send_command(utils, FLASH_REG_ACCESS, &mail_box_tlv, reg_size, reg_size); - MLX_CHECK_STATUS(utils, status, icmd_err, "failed to send icmd"); - - mlx_memory_cpy(utils, reg_data, &mail_box_tlv.reg_tlv.data, - reg_size - (OP_TLV_SIZE + REG_TLV_HEADER_LEN)); - - *reg_status = mail_box_tlv.operation_tlv.status; -icmd_err: -bad_param: - return status; -} - - diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_reg_access/mlx_reg_access.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_reg_access/mlx_reg_access.h deleted file mode 100644 index 9fbf51631..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_reg_access/mlx_reg_access.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef MLX_REG_ACCESS_H_ -#define MLX_REG_ACCESS_H_ - -#include "../../include/public/mlx_icmd.h" - -#define REG_ACCESS_MAX_REG_SIZE 236 - -typedef enum { - REG_ACCESS_READ = 1, - REG_ACCESS_WRITE = 2, -} REG_ACCESS_OPT; - -typedef enum { - TLV_ACCESS_DEFAULT_DIS = 0, - TLV_ACCESS_DEFAULT_EN = 1, -} NV_DEFAULT_OPT; - -#define REG_ID_NVDA 0x9024 -#define REG_ID_NVDI 0x9025 -#define REG_ID_NVIA 0x9029 -#define REG_ID_MLCR 0x902b -#define REG_ID_NVQC 0x9030 -#define REG_ID_MFRL 0x9028 -#define REG_ID_PTYS 0x5004 -#define REG_ID_PMTU 0x5003 - -struct operation_tlv { - mlx_uint32 reserved0 :8; /* bit_offset:0 */ /* element_size: 8 */ - mlx_uint32 status :7; /* bit_offset:8 */ /* element_size: 7 */ - mlx_uint32 dr :1; /* bit_offset:15 */ /* element_size: 1 */ - mlx_uint32 len :11; /* bit_offset:16 */ /* element_size: 11 */ - mlx_uint32 Type :5; /* bit_offset:27 */ /* element_size: 5 */ - mlx_uint32 cls :8; /* bit_offset:32 */ /* element_size: 8 */ - mlx_uint32 method :7; /* bit_offset:40 */ /* element_size: 7 */ - mlx_uint32 r :1; /* bit_offset:47 */ /* element_size: 1 */ - mlx_uint32 register_id :16; /* bit_offset:48 */ /* element_size: 16 */ - mlx_uint64 tid ; /* bit_offset:64 */ /* element_size: 64 */ -}; - -struct reg_tlv { - mlx_uint32 reserved0 :16; /* bit_offset:0 */ /* element_size: 16 */ - mlx_uint32 len :11; /* bit_offset:16 */ /* element_size: 11 */ - mlx_uint32 Type :5; /* bit_offset:27 */ /* element_size: 5 */ - mlx_uint8 data[REG_ACCESS_MAX_REG_SIZE]; -}; - -struct mail_box_tlv { - struct operation_tlv operation_tlv; - struct reg_tlv reg_tlv; -}; -mlx_status -mlx_reg_access( - IN mlx_utils *utils, - IN mlx_uint16 reg_id, - IN REG_ACCESS_OPT reg_opt, - IN OUT mlx_void *reg_data, - IN mlx_size reg_size, - OUT mlx_uint32 *reg_status - ); - -#endif /* MLX_REG_ACCESS_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_vmac/mlx_vmac.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_vmac/mlx_vmac.c deleted file mode 100644 index 65d04c967..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_vmac/mlx_vmac.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../mlx_lib/mlx_vmac/mlx_vmac.h" -#include "../../include/public/mlx_icmd.h" -#include "../../include/public/mlx_bail.h" - -mlx_status -mlx_vmac_query_virt_mac ( - IN mlx_utils *utils, - OUT struct mlx_vmac_query_virt_mac *virt_mac - ) -{ - mlx_status status = MLX_SUCCESS; - if (utils == NULL || virt_mac == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = mlx_icmd_send_command( - utils, - QUERY_VIRTUAL_MAC, - virt_mac, - 0, - sizeof(*virt_mac) - ); - MLX_CHECK_STATUS(utils, status, icmd_err, "mlx_icmd_send_command failed"); -icmd_err: -bad_param: - return status; -} - -mlx_status -mlx_vmac_set_virt_mac ( - IN mlx_utils *utils, - OUT struct mlx_vmac_set_virt_mac *virt_mac - ) -{ - mlx_status status = MLX_SUCCESS; - if (utils == NULL || virt_mac == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - status = mlx_icmd_send_command( - utils, - SET_VIRTUAL_MAC, - virt_mac, - sizeof(*virt_mac), - 0 - ); - MLX_CHECK_STATUS(utils, status, icmd_err, "mlx_icmd_send_command failed"); -icmd_err: -bad_param: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_vmac/mlx_vmac.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_vmac/mlx_vmac.h deleted file mode 100644 index 2214d9189..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_vmac/mlx_vmac.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef MLX_VMAC_H_ -#define MLX_VMAC_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../include/public/mlx_utils.h" - -struct mlx_vmac_query_virt_mac { - mlx_uint32 reserved0 :30; - mlx_uint32 mac_aux_v :1; - mlx_uint32 virtual_mac_en :1; - mlx_uint32 parmanent_mac_high :16; - mlx_uint32 reserved1 :16; - mlx_uint32 parmanent_mac_low :32; - mlx_uint32 virtual_mac_high :16; - mlx_uint32 Reserved2 :16; - mlx_uint32 virtual_mac_low :32; -}; - -struct mlx_vmac_set_virt_mac { - mlx_uint32 Reserved0 :30; - mlx_uint32 mac_aux_v :1; - mlx_uint32 virtual_mac_en :1; - mlx_uint32 reserved1 :32; - mlx_uint32 reserved2 :32; - mlx_uint32 virtual_mac_high; - mlx_uint32 virtual_mac_low; -}; - -mlx_status -mlx_vmac_query_virt_mac ( - IN mlx_utils *utils, - OUT struct mlx_vmac_query_virt_mac *virt_mac - ); - -mlx_status -mlx_vmac_set_virt_mac ( - IN mlx_utils *utils, - OUT struct mlx_vmac_set_virt_mac *virt_mac - ); -#endif /* MLX_VMAC_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_wol_rol/mlx_wol_rol.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_wol_rol/mlx_wol_rol.c deleted file mode 100644 index a6c23c4a1..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_wol_rol/mlx_wol_rol.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "mlx_wol_rol.h" -#include "mlx_icmd.h" -#include "mlx_memory.h" -#include "mlx_bail.h" - -mlx_status -mlx_set_wol ( - IN mlx_utils *utils, - IN mlx_uint8 wol_mask - ) -{ - mlx_status status = MLX_SUCCESS; - struct mlx_wol_rol wol_rol; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - mlx_memory_set(utils, &wol_rol, 0, sizeof(wol_rol)); - wol_rol.wol_mode_valid = TRUE; - wol_rol.wol_mode = wol_mask; - status = mlx_icmd_send_command( - utils, - SET_WOL_ROL, - &wol_rol, - sizeof(wol_rol), - 0 - ); - MLX_CHECK_STATUS(utils, status, icmd_err, "mlx_icmd_send_command failed"); -icmd_err: -bad_param: - return status; -} - -mlx_status -mlx_query_wol ( - IN mlx_utils *utils, - OUT mlx_uint8 *wol_mask - ) -{ - mlx_status status = MLX_SUCCESS; - struct mlx_wol_rol wol_rol; - - if (utils == NULL || wol_mask == NULL) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - mlx_memory_set(utils, &wol_rol, 0, sizeof(wol_rol)); - status = mlx_icmd_send_command( - utils, - QUERY_WOL_ROL, - &wol_rol, - 0, - sizeof(wol_rol) - ); - MLX_CHECK_STATUS(utils, status, icmd_err, "mlx_icmd_send_command failed"); - *wol_mask = wol_rol.wol_mode; -icmd_err: -bad_param: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_wol_rol/mlx_wol_rol.h b/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_wol_rol/mlx_wol_rol.h deleted file mode 100644 index 610419d5d..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/mlx_lib/mlx_wol_rol/mlx_wol_rol.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef MLX_WOL_ROL_H_ -#define MLX_WOL_ROL_H_ - -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - - -#include "mlx_utils.h" - -typedef enum { - WOL_MODE_DISABLE = 0x0, - WOL_MODE_SECURE = 0x2, - WOL_MODE_MAGIC = 0x4, - WOL_MODE_ARP = 0x8, - WOL_MODE_BC = 0x10, - WOL_MODE_MC = 0x20, - WOL_MODE_UC = 0x40, - WOL_MODE_PHY = 0x80, -} WOL_MODE; - -struct mlx_wol_rol { - mlx_uint32 reserved0 :32; - mlx_uint32 reserved1 :32; - mlx_uint32 wol_mode :8; - mlx_uint32 rol_mode :8; - mlx_uint32 reserved3 :14; - mlx_uint32 wol_mode_valid :1; - mlx_uint32 rol_mode_valid :1; -}; - -mlx_status -mlx_set_wol ( - IN mlx_utils *utils, - IN mlx_uint8 wol_mask - ); - -mlx_status -mlx_query_wol ( - IN mlx_utils *utils, - OUT mlx_uint8 *wol_mask - ); - -#endif /* MLX_WOL_ROL_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/private/uefi/mlx_logging_impl.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/src/private/uefi/mlx_logging_impl.c deleted file mode 100644 index 4386ad9b9..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/private/uefi/mlx_logging_impl.c +++ /dev/null @@ -1,9 +0,0 @@ -MlxDebugLogImpl() - { - DBGC((DEBUG),""); - } -MlxInfoLogImpl() -{ - DBGC((INFO),""); - } -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_icmd.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_icmd.c deleted file mode 100644 index f7d365dee..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_icmd.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../include/public/mlx_bail.h" -#include "../../include/public/mlx_icmd.h" -#include "../../include/public/mlx_pci_gw.h" -#include "../../include/public/mlx_utils.h" - -static -mlx_status -mlx_icmd_get_semaphore( - IN mlx_utils *utils - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 retries = 0; - mlx_uint32 semaphore_id; - mlx_uint32 buffer; - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto invalid_param; - } - - status = mlx_utils_rand(utils, &semaphore_id); - MLX_CHECK_STATUS(utils, status, rand_err, "failed to get random number"); -#define ICMD_GET_SEMAPHORE_TRIES 2560 - for (retries = 0 ; retries < ICMD_GET_SEMAPHORE_TRIES ; retries++) { - status = mlx_pci_gw_read( utils, PCI_GW_SPACE_SEMAPHORE, - MLX_ICMD_SEMAPHORE_ADDR, &buffer); - MLX_CHECK_STATUS(utils, status, read_err, "failed to read icmd semaphore"); - if (buffer != 0) { - mlx_utils_delay_in_ms(10); - continue; - } - mlx_pci_gw_write( utils, PCI_GW_SPACE_SEMAPHORE, - MLX_ICMD_SEMAPHORE_ADDR, semaphore_id); - MLX_CHECK_STATUS(utils, status, set_err, "failed to set icmd semaphore"); - status = mlx_pci_gw_read( utils, PCI_GW_SPACE_SEMAPHORE, - MLX_ICMD_SEMAPHORE_ADDR, &buffer); - MLX_CHECK_STATUS(utils, status, read_err, "failed to read icmd semaphore"); - if (semaphore_id == buffer) { - status = MLX_SUCCESS; - utils->icmd.took_semaphore = TRUE; - break; - } - mlx_utils_delay_in_ms(10); - } - if (semaphore_id != buffer) { - status = MLX_FAILED; - } -read_err: -set_err: -rand_err: -invalid_param: - return status; -} -static -mlx_status -mlx_icmd_clear_semaphore( - IN mlx_utils *utils - ) -{ - mlx_status status = MLX_SUCCESS; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto invalid_param; - } - - if (utils->icmd.took_semaphore == FALSE) { - goto semaphore_not_taken; - } - status = mlx_pci_gw_write( utils, PCI_GW_SPACE_SEMAPHORE, - MLX_ICMD_SEMAPHORE_ADDR, 0); - MLX_CHECK_STATUS(utils, status, read_err, "failed to clear icmd semaphore"); - - utils->icmd.took_semaphore = FALSE; -read_err: -semaphore_not_taken: -invalid_param: - return status; -} - -static -mlx_status -mlx_icmd_init( - IN mlx_utils *utils - ) -{ - mlx_status status = MLX_SUCCESS; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto invalid_param; - } - if (utils->icmd.icmd_opened == TRUE) { - goto already_opened; - } - - utils->icmd.took_semaphore = FALSE; - - status = mlx_pci_gw_read( utils, PCI_GW_SPACE_ALL_ICMD, - MLX_ICMD_MB_SIZE_ADDR, &utils->icmd.max_cmd_size); - MLX_CHECK_STATUS(utils, status, read_err, "failed to read icmd mail box size"); - - utils->icmd.icmd_opened = TRUE; -read_err: -already_opened: -invalid_param: - return status; -} - -static -mlx_status -mlx_icmd_set_opcode( - IN mlx_utils *utils, - IN mlx_uint16 opcode - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto invalid_param; - } - - status = mlx_pci_gw_read( utils, PCI_GW_SPACE_ALL_ICMD, - MLX_ICMD_CTRL_ADDR, &buffer); - MLX_CHECK_STATUS(utils, status, read_err, "failed to read icmd ctrl"); - -#define MLX_ICMD_OPCODE_ALIGN 16 -#define MLX_ICMD_OPCODE_MASK 0xffff - - buffer = buffer & ~(MLX_ICMD_OPCODE_MASK << MLX_ICMD_OPCODE_ALIGN); - buffer = buffer | (opcode << MLX_ICMD_OPCODE_ALIGN); - - status = mlx_pci_gw_write( utils, PCI_GW_SPACE_ALL_ICMD, - MLX_ICMD_CTRL_ADDR, buffer); - MLX_CHECK_STATUS(utils, status, write_err, "failed to write icmd ctrl"); -write_err: -read_err: -invalid_param: - return status; -} - -static -mlx_status -mlx_icmd_go( - IN mlx_utils *utils - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer; - mlx_uint32 busy; - mlx_uint32 wait_iteration = 0; - - if (utils == NULL) { - status = MLX_INVALID_PARAMETER; - goto invalid_param; - } - - status = mlx_pci_gw_read( utils, PCI_GW_SPACE_ALL_ICMD, - MLX_ICMD_CTRL_ADDR, &buffer); - MLX_CHECK_STATUS(utils, status, read_err, "failed to read icmd ctrl"); - -#define MLX_ICMD_BUSY_ALIGN 0 -#define MLX_ICMD_BUSY_MASK 0x1 - - busy = (buffer >> MLX_ICMD_BUSY_ALIGN) & MLX_ICMD_BUSY_MASK; - if (busy != 0) { - status = MLX_FAILED; - goto already_busy; - } - - buffer = buffer | (1 << MLX_ICMD_BUSY_ALIGN); - - status = mlx_pci_gw_write( utils, PCI_GW_SPACE_ALL_ICMD, - MLX_ICMD_CTRL_ADDR, buffer); - MLX_CHECK_STATUS(utils, status, write_err, "failed to write icmd ctrl"); - -#define MLX_ICMD_BUSY_MAX_ITERATIONS 1024 - do { - if (++wait_iteration > MLX_ICMD_BUSY_MAX_ITERATIONS) { - status = MLX_FAILED; - MLX_DEBUG_ERROR(utils, "ICMD time out"); - goto busy_timeout; - } - - mlx_utils_delay_in_ms(10); - status = mlx_pci_gw_read( utils, PCI_GW_SPACE_ALL_ICMD, - MLX_ICMD_CTRL_ADDR, &buffer); - MLX_CHECK_STATUS(utils, status, read_err, "failed to read icmd ctrl"); - busy = (buffer >> MLX_ICMD_BUSY_ALIGN) & MLX_ICMD_BUSY_MASK; - } while (busy != 0); - -busy_timeout: -write_err: -already_busy: -read_err: -invalid_param: - return status; -} - -static -mlx_status -mlx_icmd_get_status( - IN mlx_utils *utils, - OUT mlx_uint32 *out_status - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 buffer; - - if (utils == NULL || out_status == NULL) { - status = MLX_INVALID_PARAMETER; - goto invalid_param; - } - - status = mlx_pci_gw_read( utils, PCI_GW_SPACE_ALL_ICMD, - MLX_ICMD_CTRL_ADDR, &buffer); - MLX_CHECK_STATUS(utils, status, read_err, "failed to read icmd ctrl"); - -#define MLX_ICMD_STATUS_ALIGN 8 -#define MLX_ICMD_STATUS_MASK 0xff - - *out_status = (buffer >> MLX_ICMD_STATUS_ALIGN) & MLX_ICMD_STATUS_MASK; - -read_err: -invalid_param: - return status; -} - -static -mlx_status -mlx_icmd_write_buffer( - IN mlx_utils *utils, - IN mlx_void* data, - IN mlx_uint32 data_size - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 data_offset = 0; - mlx_size dword_size = sizeof(mlx_uint32); - - if (utils == NULL || data == NULL) { - status = MLX_INVALID_PARAMETER; - goto invalid_param; - } - - for (data_offset = 0 ; data_offset*dword_size < data_size ; data_offset++) { - status = mlx_pci_gw_write( utils, PCI_GW_SPACE_ALL_ICMD, - MLX_ICMD_MB_ADDR + data_offset*dword_size, - ((mlx_uint32*)data)[data_offset]); - MLX_CHECK_STATUS(utils, status, write_err, "failed to write icmd MB"); - } -write_err: -invalid_param: - return status; -} - - -static -mlx_status -mlx_icmd_read_buffer( - IN mlx_utils *utils, - OUT mlx_void* data, - IN mlx_uint32 data_size - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 data_offset = 0; - mlx_size dword_size = sizeof(mlx_uint32); - - if (utils == NULL || data == NULL) { - status = MLX_INVALID_PARAMETER; - goto invalid_param; - } - - for (data_offset = 0 ; data_offset*dword_size < data_size ; data_offset++) { - status = mlx_pci_gw_read( utils, PCI_GW_SPACE_ALL_ICMD, - MLX_ICMD_MB_ADDR + data_offset*dword_size, - (mlx_uint32*)data + data_offset); - MLX_CHECK_STATUS(utils, status, read_err, "failed to read icmd MB"); - } -read_err: -invalid_param: - return status; -} -mlx_status -mlx_icmd_send_command( - IN mlx_utils *utils, - IN mlx_uint16 opcode, - IN OUT mlx_void* data, - IN mlx_uint32 write_data_size, - IN mlx_uint32 read_data_size - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 icmd_status = MLX_FAILED; - - if (utils == NULL || data == NULL) { - status = MLX_INVALID_PARAMETER; - goto invalid_param; - } - status = mlx_icmd_init(utils); - MLX_CHECK_STATUS(utils, status, open_err, "failed to open icmd"); - - if (write_data_size > utils->icmd.max_cmd_size || - read_data_size > utils->icmd.max_cmd_size) { - status = MLX_INVALID_PARAMETER; - goto size_err; - } - - status = mlx_icmd_get_semaphore(utils); - MLX_CHECK_STATUS(utils, status, semaphore_err, "failed to get icmd semaphore"); - - status = mlx_icmd_set_opcode(utils, opcode); - MLX_CHECK_STATUS(utils, status, opcode_err, "failed to set icmd opcode"); - - if (write_data_size != 0) { - status = mlx_icmd_write_buffer(utils, data, write_data_size); - MLX_CHECK_STATUS(utils, status, opcode_err, "failed to write icmd MB"); - } - - status = mlx_icmd_go(utils); - MLX_CHECK_STATUS(utils, status, go_err, "failed to activate icmd"); - - status = mlx_icmd_get_status(utils, &icmd_status); - MLX_CHECK_STATUS(utils, status, get_status_err, "failed to set icmd opcode"); - - if (icmd_status != 0) { - MLX_DEBUG_ERROR(utils, "icmd failed with status = %d\n", icmd_status); - status = MLX_FAILED; - goto icmd_failed; - } - if (read_data_size != 0) { - status = mlx_icmd_read_buffer(utils, data, read_data_size); - MLX_CHECK_STATUS(utils, status, read_err, "failed to read icmd MB"); - } -read_err: -icmd_failed: -get_status_err: -go_err: -opcode_err: - mlx_icmd_clear_semaphore(utils); -semaphore_err: -size_err: -open_err: -invalid_param: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_memory.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_memory.c deleted file mode 100644 index 5aa5a53d2..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_memory.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stddef.h> -#include "../../include/private/mlx_memory_priv.h" -#include "../../include/public/mlx_memory.h" - -mlx_status -mlx_memory_alloc( - IN mlx_utils *utils, - IN mlx_size size, - OUT mlx_void **ptr - ) -{ - mlx_status status = MLX_SUCCESS; - *ptr = NULL; - if ( utils == NULL || size == 0 || *ptr != NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_alloc_priv(utils, size, ptr); -bad_param: - return status; -} - -mlx_status -mlx_memory_zalloc( - IN mlx_utils *utils, - IN mlx_size size, - OUT mlx_void **ptr - ) -{ - mlx_status status = MLX_SUCCESS; - *ptr = NULL; - if ( utils == NULL || size == 0 || *ptr != NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_zalloc_priv(utils, size, ptr); -bad_param: - return status; -} - -mlx_status -mlx_memory_free( - IN mlx_utils *utils, - IN mlx_void **ptr - ) -{ - mlx_status status = MLX_SUCCESS; - if ( utils == NULL || ptr == NULL || *ptr == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_free_priv(utils, *ptr); - *ptr = NULL; -bad_param: - return status; -} -mlx_status -mlx_memory_alloc_dma( - IN mlx_utils *utils, - IN mlx_size size , - IN mlx_size align, - OUT mlx_void **ptr - ) -{ - mlx_status status = MLX_SUCCESS; - *ptr = NULL; - if ( utils == NULL || size == 0 || *ptr != NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_alloc_dma_priv(utils, size, align, ptr); -bad_param: - return status; -} - -mlx_status -mlx_memory_free_dma( - IN mlx_utils *utils, - IN mlx_size size , - IN mlx_void **ptr - ) -{ - mlx_status status = MLX_SUCCESS; - if ( utils == NULL || size == 0 || ptr == NULL || *ptr == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_free_dma_priv(utils, size, *ptr); - *ptr = NULL; -bad_param: - return status; -} - -mlx_status -mlx_memory_map_dma( - IN mlx_utils *utils, - IN mlx_void *addr , - IN mlx_size number_of_bytes, - OUT mlx_physical_address *phys_addr, - OUT mlx_void **mapping - ) -{ - mlx_status status = MLX_SUCCESS; - if ( utils == NULL || phys_addr == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_map_dma_priv(utils, addr, number_of_bytes, phys_addr, mapping); -bad_param: - return status; -} - -mlx_status -mlx_memory_ummap_dma( - IN mlx_utils *utils, - IN mlx_void *mapping - ) -{ - mlx_status status = MLX_SUCCESS; - if ( utils == NULL){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_ummap_dma_priv(utils, mapping); -bad_param: - return status; -} - -mlx_status -mlx_memory_cmp( - IN mlx_utils *utils, - IN mlx_void *first_block, - IN mlx_void *second_block, - IN mlx_size size, - OUT mlx_uint32 *out - ) -{ - mlx_status status = MLX_SUCCESS; - if ( utils == NULL || first_block == NULL || second_block == NULL || - out == NULL){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_cmp_priv(utils, first_block, second_block, size, out); -bad_param: - return status; -} - -mlx_status -mlx_memory_set( - IN mlx_utils *utils, - IN mlx_void *block, - IN mlx_int32 value, - IN mlx_size size - ) -{ - mlx_status status = MLX_SUCCESS; - if ( utils == NULL || block == NULL){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_set_priv(utils, block, value, size); -bad_param: - return status; -} - -mlx_status -mlx_memory_cpy( - IN mlx_utils *utils, - OUT mlx_void *destination_buffer, - IN mlx_void *source_buffer, - IN mlx_size length - ) -{ - mlx_status status = MLX_SUCCESS; - if ( utils == NULL || destination_buffer == NULL || source_buffer == NULL){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_cpy_priv(utils, destination_buffer, source_buffer, length); -bad_param: - return status; -} - -mlx_status -mlx_memory_cpu_to_be32( - IN mlx_utils *utils, - IN mlx_uint32 source, - IN mlx_uint32 *destination - ) -{ - mlx_status status = MLX_SUCCESS; - if ( utils == NULL || destination == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_cpu_to_be32_priv(utils, source, destination); -bad_param: - return status; -} - -mlx_status -mlx_memory_be32_to_cpu( - IN mlx_utils *utils, - IN mlx_uint32 source, - IN mlx_uint32 *destination - ) -{ - mlx_status status = MLX_SUCCESS; - if ( utils == NULL || destination == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - status = mlx_memory_be32_to_cpu_priv(utils, source, destination); -bad_param: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_pci.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_pci.c deleted file mode 100644 index 91c44d991..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_pci.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stddef.h> -#include "../../include/private/mlx_pci_priv.h" -#include "../../include/public/mlx_pci.h" - -mlx_status -mlx_pci_init( - IN mlx_utils *utils - ) -{ - mlx_status status = MLX_SUCCESS; - if( utils == NULL){ - status = MLX_INVALID_PARAMETER; - goto bail; - } - status = mlx_pci_init_priv(utils); -bail: - return status; -} - -mlx_status -mlx_pci_read( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint32 offset, - IN mlx_uintn count, - OUT mlx_void *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - if( utils == NULL || count == 0){ - status = MLX_INVALID_PARAMETER; - goto bail; - } - status = mlx_pci_read_priv(utils, width, offset, count, buffer); -bail: - return status; -} - -mlx_status -mlx_pci_write( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint32 offset, - IN mlx_uintn count, - IN mlx_void *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - if( utils == NULL || count == 0){ - status = MLX_INVALID_PARAMETER; - goto bail; - } - status = mlx_pci_write_priv(utils, width, offset, count, buffer); -bail: - return status; -} - -mlx_status -mlx_pci_mem_read( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint8 bar_index, - IN mlx_uint64 offset, - IN mlx_uintn count, - OUT mlx_void *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - if( utils == NULL || count == 0){ - status = MLX_INVALID_PARAMETER; - goto bail; - } - status = mlx_pci_mem_read_priv(utils, bar_index, width, offset, count, buffer); -bail: - return status; -} - -mlx_status -mlx_pci_mem_write( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint8 bar_index, - IN mlx_uint64 offset, - IN mlx_uintn count, - IN mlx_void *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - if( utils == NULL || count == 0){ - status = MLX_INVALID_PARAMETER; - goto bail; - } - status = mlx_pci_mem_write_priv(utils, width, bar_index, offset, count, buffer); -bail: - return status; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_pci_gw.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_pci_gw.c deleted file mode 100644 index 30c1e644e..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_pci_gw.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include "../../include/public/mlx_pci_gw.h" -#include "../../include/public/mlx_bail.h" -#include "../../include/public/mlx_pci.h" -#include "../../include/public/mlx_logging.h" - -/* Lock/unlock GW on each VSEC access */ -#undef VSEC_DEBUG - -static -mlx_status -mlx_pci_gw_check_capability_id( - IN mlx_utils *utils, - IN mlx_uint8 cap_pointer, - OUT mlx_boolean *bool - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint8 offset = cap_pointer + PCI_GW_CAPABILITY_ID_OFFSET; - mlx_uint8 id = 0; - status = mlx_pci_read(utils, MlxPciWidthUint8, offset, - 1, &id); - MLX_CHECK_STATUS(utils, status, read_err,"failed to read capability id"); - *bool = ( id == PCI_GW_CAPABILITY_ID ); -read_err: - return status; -} - -static -mlx_status -mlx_pci_gw_get_ownership( - IN mlx_utils *utils - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 cap_offset = utils->pci_gw.pci_cmd_offset; - mlx_uint32 semaphore = 0; - mlx_uint32 counter = 0; - mlx_uint32 get_semaphore_try = 0; - mlx_uint32 get_ownership_try = 0; - - for( ; get_ownership_try < PCI_GW_GET_OWNERSHIP_TRIES; get_ownership_try ++){ - for( ; get_semaphore_try <= PCI_GW_SEMPHORE_TRIES ; get_semaphore_try++){ - status = mlx_pci_read(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_SEMAPHORE_OFFSET, - 1, &semaphore); - MLX_CHECK_STATUS(utils, status, read_err,"failed to read semaphore"); - if( semaphore == 0 ){ - break; - } - mlx_utils_delay_in_us(10); - } - if( semaphore != 0 ){ - status = MLX_FAILED; - goto semaphore_err; - } - - status = mlx_pci_read(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_COUNTER_OFFSET, - 1, &counter); - MLX_CHECK_STATUS(utils, status, read_err, "failed to read counter"); - - status = mlx_pci_write(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_SEMAPHORE_OFFSET, - 1, &counter); - MLX_CHECK_STATUS(utils, status, write_err,"failed to write semaphore"); - - status = mlx_pci_read(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_SEMAPHORE_OFFSET, - 1, &semaphore); - MLX_CHECK_STATUS(utils, status, read_err,"failed to read semaphore"); - if( counter == semaphore ){ - break; - } - } - if( counter != semaphore ){ - status = MLX_FAILED; - } -write_err: -read_err: -semaphore_err: - return status; -} - -static -mlx_status -mlx_pci_gw_free_ownership( - IN mlx_utils *utils - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 cap_offset = utils->pci_gw.pci_cmd_offset; - mlx_uint32 value = 0; - - status = mlx_pci_write(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_SEMAPHORE_OFFSET, - 1, &value); - MLX_CHECK_STATUS(utils, status, write_err,"failed to write semaphore"); -write_err: - return status; -} - -static -mlx_status -mlx_pci_gw_set_space( - IN mlx_utils *utils, - IN mlx_pci_gw_space space - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 cap_offset = utils->pci_gw.pci_cmd_offset;; - mlx_uint8 space_status = 0; - - /* set nodnic*/ - status = mlx_pci_write(utils, MlxPciWidthUint16, cap_offset + PCI_GW_CAPABILITY_SPACE_OFFSET, 1, &space); - MLX_CHECK_STATUS(utils, status, read_error,"failed to write capability space"); - - status = mlx_pci_read(utils, MlxPciWidthUint8, cap_offset + PCI_GW_CAPABILITY_STATUS_OFFSET, 1, &space_status); - MLX_CHECK_STATUS(utils, status, read_error,"failed to read capability status"); - if( (space_status & 0x20) == 0){ - status = MLX_FAILED; - goto space_unsupported; - } -read_error: -space_unsupported: - return status; -} - -static -mlx_status -mlx_pci_gw_wait_for_flag_value( - IN mlx_utils *utils, - IN mlx_boolean value - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint32 try = 0; - mlx_uint32 cap_offset = utils->pci_gw.pci_cmd_offset; - mlx_uint32 flag = 0; - - for(; try < PCI_GW_READ_FLAG_TRIES ; try ++ ) { - status = mlx_pci_read(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_FLAG_OFFSET, 1, &flag); - MLX_CHECK_STATUS(utils, status, read_error, "failed to read capability flag"); - if( ((flag & 0x80000000) != 0) == value ){ - goto flag_valid; - } - mlx_utils_delay_in_us(10); - } - status = MLX_FAILED; -flag_valid: -read_error: - return status; -} -static -mlx_status -mlx_pci_gw_search_capability( - IN mlx_utils *utils, - OUT mlx_uint32 *cap_offset - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint8 cap_pointer = 0; - mlx_boolean is_capability = FALSE; - - if( cap_offset == NULL || utils == NULL){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - //get first capability pointer - status = mlx_pci_read(utils, MlxPciWidthUint8, PCI_GW_FIRST_CAPABILITY_POINTER_OFFSET, - 1, &cap_pointer); - MLX_CHECK_STATUS(utils, status, read_err, - "failed to read capability pointer"); - - //search the right capability - while( cap_pointer != 0 ){ - status = mlx_pci_gw_check_capability_id(utils, cap_pointer, &is_capability); - MLX_CHECK_STATUS(utils, status, check_err - ,"failed to check capability id"); - - if( is_capability == TRUE ){ - *cap_offset = cap_pointer; - break; - } - - status = mlx_pci_read(utils, MlxPciWidthUint8, cap_pointer + - PCI_GW_CAPABILITY_NEXT_POINTER_OFFSET , - 1, &cap_pointer); - MLX_CHECK_STATUS(utils, status, read_err, - "failed to read capability pointer"); - } - if( is_capability != TRUE ){ - status = MLX_NOT_FOUND; - } -check_err: -read_err: -bad_param: - return status; -} - -mlx_status -mlx_pci_gw_init( - IN mlx_utils *utils - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_pci_gw *pci_gw = NULL; - - if( utils == NULL){ - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - pci_gw = &utils->pci_gw; - - status = mlx_pci_gw_search_capability(utils, &pci_gw->pci_cmd_offset); - MLX_CHECK_STATUS(utils, status, cap_err, - "mlx_pci_gw_search_capability failed"); - -#if ! defined ( VSEC_DEBUG ) - status = mlx_pci_gw_get_ownership(utils); - MLX_CHECK_STATUS(utils, status, ownership_err,"failed to get ownership"); -ownership_err: -#endif -cap_err: -bad_param: - return status; -} - -mlx_status -mlx_pci_gw_teardown( - IN mlx_utils *utils __attribute__ ((unused)) - ) -{ -#if ! defined ( VSEC_DEBUG ) - mlx_pci_gw_free_ownership(utils); -#endif - return MLX_SUCCESS; -} - -mlx_status -mlx_pci_gw_read( - IN mlx_utils *utils, - IN mlx_pci_gw_space space, - IN mlx_uint32 address, - OUT mlx_pci_gw_buffer *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_pci_gw *pci_gw = NULL; - mlx_uint32 cap_offset = 0; - - if (utils == NULL || buffer == NULL || utils->pci_gw.pci_cmd_offset == 0) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - mlx_utils_acquire_lock(utils); - - pci_gw = &utils->pci_gw; - cap_offset = pci_gw->pci_cmd_offset; - -#if ! defined ( VSEC_DEBUG ) - if (pci_gw->space != space) { - status = mlx_pci_gw_set_space(utils, space); - MLX_CHECK_STATUS(utils, status, space_error,"failed to set space"); - pci_gw->space = space; - } -#else - status = mlx_pci_gw_get_ownership(utils); - MLX_CHECK_STATUS(utils, status, ownership_err,"failed to get ownership"); - - status = mlx_pci_gw_set_space(utils, space); - MLX_CHECK_STATUS(utils, status, space_error,"failed to set space"); - pci_gw->space = space; -#endif - - status = mlx_pci_write(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_ADDRESS_OFFSET, 1, &address); - MLX_CHECK_STATUS(utils, status, read_error,"failed to write capability address"); - -#if defined ( DEVICE_CX3 ) - /* WA for PCI issue (race) */ - mlx_utils_delay_in_us ( 10 ); -#endif - - status = mlx_pci_gw_wait_for_flag_value(utils, TRUE); - MLX_CHECK_STATUS(utils, status, read_error, "flag failed to change"); - - status = mlx_pci_read(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_DATA_OFFSET, 1, buffer); - MLX_CHECK_STATUS(utils, status, read_error,"failed to read capability data"); - -#if defined ( VSEC_DEBUG ) - status = mlx_pci_gw_free_ownership(utils); - MLX_CHECK_STATUS(utils, status, free_err, - "mlx_pci_gw_free_ownership failed"); -free_err: - mlx_utils_release_lock(utils); - return status; -#endif -read_error: -space_error: -#if defined ( VSEC_DEBUG ) - mlx_pci_gw_free_ownership(utils); -ownership_err: -#endif -mlx_utils_release_lock(utils); -bad_param: - return status; -} - -mlx_status -mlx_pci_gw_write( - IN mlx_utils *utils, - IN mlx_pci_gw_space space, - IN mlx_uint32 address, - IN mlx_pci_gw_buffer buffer - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_pci_gw *pci_gw = NULL; - mlx_uint32 cap_offset = 0; - mlx_uint32 fixed_address = address | PCI_GW_WRITE_FLAG; - - if (utils == NULL || utils->pci_gw.pci_cmd_offset == 0) { - status = MLX_INVALID_PARAMETER; - goto bad_param; - } - - mlx_utils_acquire_lock(utils); - - pci_gw = &utils->pci_gw; - cap_offset = pci_gw->pci_cmd_offset; - -#if ! defined ( VSEC_DEBUG ) - if (pci_gw->space != space) { - status = mlx_pci_gw_set_space(utils, space); - MLX_CHECK_STATUS(utils, status, space_error,"failed to set space"); - pci_gw->space = space; - } -#else - status = mlx_pci_gw_get_ownership(utils); - MLX_CHECK_STATUS(utils, status, ownership_err,"failed to get ownership"); - - status = mlx_pci_gw_set_space(utils, space); - MLX_CHECK_STATUS(utils, status, space_error,"failed to set space"); - pci_gw->space = space; -#endif - status = mlx_pci_write(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_DATA_OFFSET, 1, &buffer); - MLX_CHECK_STATUS(utils, status, read_error,"failed to write capability data"); - - status = mlx_pci_write(utils, MlxPciWidthUint32, cap_offset + PCI_GW_CAPABILITY_ADDRESS_OFFSET, 1, &fixed_address); - MLX_CHECK_STATUS(utils, status, read_error,"failed to write capability address"); - - status = mlx_pci_gw_wait_for_flag_value(utils, FALSE); - MLX_CHECK_STATUS(utils, status, read_error, "flag failed to change"); -#if defined ( VSEC_DEBUG ) - status = mlx_pci_gw_free_ownership(utils); - MLX_CHECK_STATUS(utils, status, free_err, - "mlx_pci_gw_free_ownership failed"); -free_err: -mlx_utils_release_lock(utils); - return status; -#endif -read_error: -space_error: -#if defined ( VSEC_DEBUG ) - mlx_pci_gw_free_ownership(utils); -ownership_err: -#endif -mlx_utils_release_lock(utils); -bad_param: - return status; -} - - - diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_utils.c b/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_utils.c deleted file mode 100644 index c824b17e9..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils/src/public/mlx_utils.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stddef.h> -#include "../../include/private/mlx_utils_priv.h" -#include "../../include/public/mlx_pci.h" -#include "../../include/public/mlx_utils.h" - -mlx_status -mlx_utils_init( - IN mlx_utils *utils, - IN mlx_pci *pci - ) -{ - mlx_status status = MLX_SUCCESS; - if( pci == NULL || utils == NULL ){ - status = MLX_INVALID_PARAMETER; - goto bail; - } - utils->pci = pci; - status = mlx_pci_init(utils); - status = mlx_utils_init_lock(utils); -bail: - return status; -} - -mlx_status -mlx_utils_teardown( - IN mlx_utils *utils __attribute__ ((unused)) - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_utils_free_lock(utils); - return status; -} - -mlx_status -mlx_utils_delay_in_ms( - IN mlx_uint32 msecs - ) -{ - mlx_utils_delay_in_ms_priv(msecs); - return MLX_SUCCESS; -} -mlx_status -mlx_utils_delay_in_us( - IN mlx_uint32 usecs - ) -{ - mlx_utils_delay_in_us_priv(usecs); - return MLX_SUCCESS; -} -mlx_status -mlx_utils_ilog2( - IN mlx_uint32 i, - OUT mlx_uint32 *log - ) -{ - mlx_utils_ilog2_priv(i, log); - return MLX_SUCCESS; -} - -mlx_status -mlx_utils_init_lock( - IN OUT mlx_utils *utils - ) -{ - return mlx_utils_init_lock_priv(&(utils->lock)); - -} - -mlx_status -mlx_utils_free_lock( - IN OUT mlx_utils *utils - ) -{ - return mlx_utils_free_lock_priv(utils->lock); -} - -mlx_status -mlx_utils_acquire_lock ( - IN OUT mlx_utils *utils - ) -{ - return mlx_utils_acquire_lock_priv(utils->lock); -} - -mlx_status -mlx_utils_release_lock ( - IN OUT mlx_utils *utils - ) -{ - return mlx_utils_release_lock_priv(utils->lock); -} - -mlx_status -mlx_utils_rand ( - IN mlx_utils *utils, - OUT mlx_uint32 *rand_num - ) -{ - return mlx_utils_rand_priv(utils, rand_num); -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/include/mlx_logging_priv.h b/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/include/mlx_logging_priv.h deleted file mode 100644 index af7e86f44..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/include/mlx_logging_priv.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * DebugPriv.h - * - * Created on: Jan 19, 2015 - * Author: maord - */ - -#ifndef STUB_MLXUTILS_INCLUDE_PRIVATE_FLEXBOOT_DEBUG_H_ -#define STUB_MLXUTILS_INCLUDE_PRIVATE_FLEXBOOT_DEBUG_H_ - -#include <stdio.h> -#include <compiler.h> - -#define MLX_DEBUG_FATAL_ERROR_PRIVATE(...) do { \ - DBG("%s: ",__func__); \ - DBG(__VA_ARGS__); \ - } while ( 0 ) - -#define MLX_DEBUG_ERROR_PRIVATE(id, ...) do { \ - DBGC(id, "%s: ",__func__); \ - DBGC(id, __VA_ARGS__); \ - } while ( 0 ) - -#define MLX_DEBUG_WARN_PRIVATE(id, ...) do { \ - DBGC(id, "%s: ",__func__); \ - DBGC(id, __VA_ARGS__); \ - } while ( 0 ) - -#define MLX_DEBUG_INFO1_PRIVATE(id, ...) do { \ - DBGC(id, "%s: ",__func__); \ - DBGC(id, __VA_ARGS__); \ - } while ( 0 ) - -#define MLX_DEBUG_INFO2_PRIVATE(id, ...) do { \ - DBGC2(id, "%s: ",__func__); \ - DBGC2(id, __VA_ARGS__); \ - } while ( 0 ) - -#define MLX_DBG_ERROR_PRIVATE(...) do { \ - DBG("%s: ",__func__); \ - DBG(__VA_ARGS__); \ - } while ( 0 ) - -#define MLX_DBG_WARN_PRIVATE(...) do { \ - DBG("%s: ",__func__); \ - DBG(__VA_ARGS__); \ - } while ( 0 ) - -#define MLX_DBG_INFO1_PRIVATE(...) do { \ - DBG("%s: ",__func__); \ - DBG(__VA_ARGS__); \ - } while ( 0 ) - -#define MLX_DBG_INFO2_PRIVATE(...) do { \ - DBG2("%s: ",__func__); \ - DBG2(__VA_ARGS__); \ - } while ( 0 ) - - - -#endif /* STUB_MLXUTILS_INCLUDE_PRIVATE_FLEXBOOT_DEBUG_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/include/mlx_types_priv.h b/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/include/mlx_types_priv.h deleted file mode 100644 index feaeae679..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/include/mlx_types_priv.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * types.h - * - * Created on: Jan 18, 2015 - * Author: maord - */ - -#ifndef A_MLXUTILS_INCLUDE_PUBLIC_TYPES_H_ -#define A_MLXUTILS_INCLUDE_PUBLIC_TYPES_H_ -#include <stdint.h> -//#include <errno.h> -#include <ipxe/pci.h> - -#define MLX_SUCCESS 0 -#define MLX_OUT_OF_RESOURCES (-1) -//(-ENOMEM) -#define MLX_INVALID_PARAMETER (-2) -//(-EINVAL) -#define MLX_UNSUPPORTED (-3) -//(-ENOSYS) -#define MLX_NOT_FOUND (-4) - -#define MLX_FAILED (-5) - -#undef TRUE -#define TRUE 1 -#undef FALSE -#define FALSE !TRUE - -typedef int mlx_status; - -typedef uint8_t mlx_uint8; -typedef uint16_t mlx_uint16; -typedef uint32_t mlx_uint32; -typedef uint64_t mlx_uint64; -typedef uint32_t mlx_uintn; - -typedef int8_t mlx_int8; -typedef int16_t mlx_int16;; -typedef int32_t mlx_int32; -typedef int64_t mlx_int64; -typedef uint8_t mlx_boolean; - -typedef struct pci_device mlx_pci; - -typedef size_t mlx_size; - -typedef void mlx_void; - -#define MAC_ADDR_LEN 6 -typedef unsigned long mlx_physical_address; -typedef union { - struct { - uint32_t low; - uint32_t high; - } __attribute__ (( packed )); - uint8_t addr[MAC_ADDR_LEN]; -} mlx_mac_address; - -#endif /* A_MLXUTILS_INCLUDE_PUBLIC_TYPES_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/src/mlx_memory_priv.c b/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/src/mlx_memory_priv.c deleted file mode 100644 index cb9e759bf..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/src/mlx_memory_priv.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * MemoryPriv.c - * - * Created on: Jan 21, 2015 - * Author: maord - */ - -#include <ipxe/malloc.h> -#include <stddef.h> -#include <byteswap.h> -#include <ipxe/io.h> -#include "../../mlx_utils/include/private/mlx_memory_priv.h" - - -mlx_status -mlx_memory_alloc_priv( - IN mlx_utils *utils __attribute__ ((unused)), - IN mlx_size size, - OUT mlx_void **ptr - ) -{ - mlx_status status = MLX_SUCCESS; - *ptr = malloc(size); - if(*ptr == NULL){ - status = MLX_OUT_OF_RESOURCES; - } - return status; -} - -mlx_status -mlx_memory_zalloc_priv( - IN mlx_utils *utils __attribute__ ((unused)), - IN mlx_size size, - OUT mlx_void **ptr - ) -{ - mlx_status status = MLX_SUCCESS; - *ptr = zalloc(size); - if(*ptr == NULL){ - status = MLX_OUT_OF_RESOURCES; - } - return status; -} - -mlx_status -mlx_memory_free_priv( - IN mlx_utils *utils __attribute__ ((unused)), - IN mlx_void *ptr - ) -{ - mlx_status status = MLX_SUCCESS; - free(ptr); - return status; -} -mlx_status -mlx_memory_alloc_dma_priv( - IN mlx_utils *utils __attribute__ ((unused)), - IN mlx_size size , - IN mlx_size align, - OUT mlx_void **ptr - ) -{ - mlx_status status = MLX_SUCCESS; - *ptr = malloc_dma(size, align); - if (*ptr == NULL) { - status = MLX_OUT_OF_RESOURCES; - } else { - memset(*ptr, 0, size); - } - return status; -} - -mlx_status -mlx_memory_free_dma_priv( - IN mlx_utils *utils __attribute__ ((unused)), - IN mlx_size size , - IN mlx_void *ptr - ) -{ - mlx_status status = MLX_SUCCESS; - free_dma(ptr, size); - return status; -} -mlx_status -mlx_memory_map_dma_priv( - IN mlx_utils *utils __attribute__ ((unused)), - IN mlx_void *addr , - IN mlx_size number_of_bytes __attribute__ ((unused)), - OUT mlx_physical_address *phys_addr, - OUT mlx_void **mapping __attribute__ ((unused)) - ) -{ - mlx_status status = MLX_SUCCESS; - *phys_addr = virt_to_bus(addr); - return status; -} - -mlx_status -mlx_memory_ummap_dma_priv( - IN mlx_utils *utils __attribute__ ((unused)), - IN mlx_void *mapping __attribute__ ((unused)) - ) -{ - mlx_status status = MLX_SUCCESS; - return status; -} - -mlx_status -mlx_memory_cmp_priv( - IN mlx_utils *utils __unused, - IN mlx_void *first_block, - IN mlx_void *second_block, - IN mlx_size size, - OUT mlx_uint32 *out - ) -{ - mlx_status status = MLX_SUCCESS; - *out = memcmp(first_block, second_block, size); - return status; -} - -mlx_status -mlx_memory_set_priv( - IN mlx_utils *utils __unused, - IN mlx_void *block, - IN mlx_int32 value, - IN mlx_size size - ) -{ - mlx_status status = MLX_SUCCESS; - memset(block, value, size); - return status; -} - -mlx_status -mlx_memory_cpy_priv( - IN mlx_utils *utils __unused, - OUT mlx_void *destination_buffer, - IN mlx_void *source_buffer, - IN mlx_size length - ) -{ - mlx_status status = MLX_SUCCESS; - memcpy(destination_buffer, source_buffer, length); - return status; -} - -mlx_status -mlx_memory_cpu_to_be32_priv( - IN mlx_utils *utils __unused, - IN mlx_uint32 source, - IN mlx_uint32 *destination - ) -{ - mlx_status status = MLX_SUCCESS; - *destination = cpu_to_be32(source); - return status; -} - - -mlx_status -mlx_memory_be32_to_cpu_priv( - IN mlx_utils *utils __unused, - IN mlx_uint32 source, - IN mlx_uint32 *destination - ) -{ - mlx_status status = MLX_SUCCESS; - *destination = be32_to_cpu(source); - return status; -} - diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/src/mlx_pci_priv.c b/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/src/mlx_pci_priv.c deleted file mode 100644 index f8caefdce..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/src/mlx_pci_priv.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * MlxPciPriv.c - * - * Created on: Jan 21, 2015 - * Author: maord - */ - -#include <ipxe/pci.h> -#include "../../mlx_utils/include/private/mlx_pci_priv.h" - - -static -mlx_status -mlx_pci_config_byte( - IN mlx_utils *utils, - IN mlx_boolean read, - IN mlx_uint32 offset, - IN OUT mlx_uint8 *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - if (read) { - status = pci_read_config_byte(utils->pci, offset, buffer); - }else { - status = pci_write_config_byte(utils->pci, offset, *buffer); - } - return status; -} - -static -mlx_status -mlx_pci_config_word( - IN mlx_utils *utils, - IN mlx_boolean read, - IN mlx_uint32 offset, - IN OUT mlx_uint16 *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - if (read) { - status = pci_read_config_word(utils->pci, offset, buffer); - }else { - status = pci_write_config_word(utils->pci, offset, *buffer); - } - return status; -} - -static -mlx_status -mlx_pci_config_dword( - IN mlx_utils *utils, - IN mlx_boolean read, - IN mlx_uint32 offset, - IN OUT mlx_uint32 *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - if (read) { - status = pci_read_config_dword(utils->pci, offset, buffer); - }else { - status = pci_write_config_dword(utils->pci, offset, *buffer); - } - return status; -} -static -mlx_status -mlx_pci_config( - IN mlx_utils *utils, - IN mlx_boolean read, - IN mlx_pci_width width, - IN mlx_uint32 offset, - IN mlx_uintn count, - IN OUT mlx_void *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - mlx_uint8 *tmp = (mlx_uint8*)buffer; - mlx_uintn iteration = 0; - if( width == MlxPciWidthUint64) { - width = MlxPciWidthUint32; - count = count * 2; - } - - for(;iteration < count ; iteration++) { - switch (width){ - case MlxPciWidthUint8: - status = mlx_pci_config_byte(utils, read , offset++, tmp++); - break; - case MlxPciWidthUint16: - status = mlx_pci_config_word(utils, read , offset, (mlx_uint16*)tmp); - tmp += 2; - offset += 2; - break; - case MlxPciWidthUint32: - status = mlx_pci_config_dword(utils, read , offset, (mlx_uint32*)tmp); - tmp += 4; - offset += 4; - break; - default: - status = MLX_INVALID_PARAMETER; - } - if(status != MLX_SUCCESS) { - goto config_error; - } - } -config_error: - return status; -} -mlx_status -mlx_pci_init_priv( - IN mlx_utils *utils - ) -{ - mlx_status status = MLX_SUCCESS; - adjust_pci_device ( utils->pci ); -#ifdef DEVICE_CX3 - utils->config = ioremap ( pci_bar_start ( utils->pci, PCI_BASE_ADDRESS_0), - 0x100000 ); -#endif - return status; -} - -mlx_status -mlx_pci_read_priv( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint32 offset, - IN mlx_uintn count, - OUT mlx_void *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - status = mlx_pci_config(utils, TRUE, width, offset, count, buffer); - return status; -} - -mlx_status -mlx_pci_write_priv( - IN mlx_utils *utils, - IN mlx_pci_width width, - IN mlx_uint32 offset, - IN mlx_uintn count, - IN mlx_void *buffer - ) -{ - mlx_status status = MLX_SUCCESS; - status = mlx_pci_config(utils, FALSE, width, offset, count, buffer); - return status; -} - -mlx_status -mlx_pci_mem_read_priv( - IN mlx_utils *utils __attribute__ ((unused)), - IN mlx_pci_width width __attribute__ ((unused)), - IN mlx_uint8 bar_index __attribute__ ((unused)), - IN mlx_uint64 offset, - IN mlx_uintn count __attribute__ ((unused)), - OUT mlx_void *buffer - ) -{ - if (buffer == NULL || width != MlxPciWidthUint32) - return MLX_INVALID_PARAMETER; - *((mlx_uint32 *)buffer) = readl(offset); - return MLX_SUCCESS; -} - -mlx_status -mlx_pci_mem_write_priv( - IN mlx_utils *utils __attribute__ ((unused)), - IN mlx_pci_width width __attribute__ ((unused)), - IN mlx_uint8 bar_index __attribute__ ((unused)), - IN mlx_uint64 offset, - IN mlx_uintn count __attribute__ ((unused)), - IN mlx_void *buffer - ) -{ - if (buffer == NULL || width != MlxPciWidthUint32) - return MLX_INVALID_PARAMETER; - barrier(); - writel(*((mlx_uint32 *)buffer), offset); - return MLX_SUCCESS; -} diff --git a/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/src/mlx_utils_priv.c b/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/src/mlx_utils_priv.c deleted file mode 100644 index 5fca406fc..000000000 --- a/roms/ipxe/src/drivers/infiniband/mlx_utils_flexboot/src/mlx_utils_priv.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * MlxUtilsPriv.c - * - * Created on: Jan 25, 2015 - * Author: maord - */ - -#include <unistd.h> -#include <stdlib.h> -#include <strings.h> -#include "../../mlx_utils/include/private/mlx_utils_priv.h" - -mlx_status -mlx_utils_delay_in_ms_priv( - IN mlx_uint32 msecs - ) -{ - mdelay(msecs); - return MLX_SUCCESS; -} - -mlx_status -mlx_utils_delay_in_us_priv( - IN mlx_uint32 usecs - ) -{ - udelay(usecs); - return MLX_SUCCESS; -} - -mlx_status -mlx_utils_ilog2_priv( - IN mlx_uint32 i, - OUT mlx_uint32 *log - ) -{ - *log = ( fls ( i ) - 1 ); - return MLX_SUCCESS; -} - -mlx_status -mlx_utils_init_lock_priv( - OUT void **lock __unused - ) -{ - return MLX_SUCCESS; -} - -mlx_status -mlx_utils_free_lock_priv( - IN void *lock __unused - ) -{ - return MLX_SUCCESS; -} - -mlx_status -mlx_utils_acquire_lock_priv ( - IN void *lock __unused - ) -{ - return MLX_SUCCESS; -} - -mlx_status -mlx_utils_release_lock_priv ( - IN void *lock __unused - ) -{ - return MLX_SUCCESS; -} - -mlx_status -mlx_utils_rand_priv ( - IN mlx_utils *utils __unused, - OUT mlx_uint32 *rand_num - ) -{ - do { - *rand_num = rand(); - } while ( *rand_num == 0 ); - return MLX_SUCCESS; -} diff --git a/roms/ipxe/src/drivers/infiniband/nodnic_prm.h b/roms/ipxe/src/drivers/infiniband/nodnic_prm.h deleted file mode 100644 index 5e0fa9890..000000000 --- a/roms/ipxe/src/drivers/infiniband/nodnic_prm.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef SRC_DRIVERS_INFINIBAND_MLX_NODNIC_INCLUDE_PRM_NODNIC_PRM_H_ -#define SRC_DRIVERS_INFINIBAND_MLX_NODNIC_INCLUDE_PRM_NODNIC_PRM_H_ - -#include "mlx_bitops.h" - -struct nodnic_wqe_segment_data_ptr_st { /* Little Endian */ - pseudo_bit_t byte_count[0x0001f]; - pseudo_bit_t always0[0x00001]; -/* -------------- */ - pseudo_bit_t l_key[0x00020]; -/* -------------- */ - pseudo_bit_t local_address_h[0x00020]; -/* -------------- */ - pseudo_bit_t local_address_l[0x00020]; -/* -------------- */ -}; - -struct MLX_DECLARE_STRUCT ( nodnic_wqe_segment_data_ptr ); - -#define HERMON_MAX_SCATTER 1 - -struct nodnic_recv_wqe { - struct nodnic_wqe_segment_data_ptr data[HERMON_MAX_SCATTER]; -} __attribute__ (( packed )); - -#endif /* SRC_DRIVERS_INFINIBAND_MLX_NODNIC_INCLUDE_PRM_NODNIC_PRM_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/nodnic_shomron_prm.h b/roms/ipxe/src/drivers/infiniband/nodnic_shomron_prm.h deleted file mode 100644 index 85cd97187..000000000 --- a/roms/ipxe/src/drivers/infiniband/nodnic_shomron_prm.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2015 Mellanox Technologies Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifndef SRC_DRIVERS_INFINIBAND_MLX_NODNIC_INCLUDE_PRM_NODNIC_SHOMRON_PRM_H_ -#define SRC_DRIVERS_INFINIBAND_MLX_NODNIC_INCLUDE_PRM_NODNIC_SHOMRON_PRM_H_ - - - -#include "nodnic_prm.h" - - -#define SHOMRON_MAX_GATHER 1 - -/* Send wqe segment ctrl */ - -struct shomronprm_wqe_segment_ctrl_send_st { /* Little Endian */ - pseudo_bit_t opcode[0x00008]; - pseudo_bit_t wqe_index[0x00010]; - pseudo_bit_t reserved1[0x00008]; -/* -------------- */ - pseudo_bit_t ds[0x00006]; /* descriptor (wqe) size in 16bytes chunk */ - pseudo_bit_t reserved2[0x00002]; - pseudo_bit_t qpn[0x00018]; -/* -------------- */ - pseudo_bit_t reserved3[0x00002]; - pseudo_bit_t ce[0x00002]; - pseudo_bit_t reserved4[0x0001c]; -/* -------------- */ - pseudo_bit_t reserved5[0x00040]; -/* -------------- */ - pseudo_bit_t mss[0x0000e]; - pseudo_bit_t reserved6[0x0000e]; - pseudo_bit_t cs13_inner[0x00001]; - pseudo_bit_t cs14_inner[0x00001]; - pseudo_bit_t cs13[0x00001]; - pseudo_bit_t cs14[0x00001]; -/* -------------- */ - pseudo_bit_t reserved7[0x00020]; -/* -------------- */ - pseudo_bit_t inline_headers1[0x00010]; - pseudo_bit_t inline_headers_size[0x0000a]; //sum size of inline_hdr1+inline_hdrs (0x10) - pseudo_bit_t reserved8[0x00006]; -/* -------------- */ - pseudo_bit_t inline_headers2[0x00020]; -/* -------------- */ - pseudo_bit_t inline_headers3[0x00020]; -/* -------------- */ - pseudo_bit_t inline_headers4[0x00020]; -/* -------------- */ - pseudo_bit_t inline_headers5[0x00020]; -}; - - - -/* Completion Queue Entry Format #### michal - fixed by gdror */ - -struct shomronprm_completion_queue_entry_st { /* Little Endian */ - - pseudo_bit_t reserved1[0x00080]; -/* -------------- */ - pseudo_bit_t reserved2[0x00010]; - pseudo_bit_t ml_path[0x00007]; - pseudo_bit_t reserved3[0x00009]; -/* -------------- */ - pseudo_bit_t slid[0x00010]; - pseudo_bit_t reserved4[0x00010]; -/* -------------- */ - pseudo_bit_t rqpn[0x00018]; - pseudo_bit_t sl[0x00004]; - pseudo_bit_t l3_hdr[0x00002]; - pseudo_bit_t reserved5[0x00002]; -/* -------------- */ - pseudo_bit_t reserved10[0x00020]; -/* -------------- */ - pseudo_bit_t srqn[0x00018]; - pseudo_bit_t reserved11[0x0008]; -/* -------------- */ - pseudo_bit_t pkey_index[0x00020]; -/* -------------- */ - pseudo_bit_t reserved6[0x00020]; -/* -------------- */ - pseudo_bit_t byte_cnt[0x00020]; -/* -------------- */ - pseudo_bit_t reserved7[0x00040]; -/* -------------- */ - pseudo_bit_t qpn[0x00018]; - pseudo_bit_t rx_drop_counter[0x00008]; -/* -------------- */ - pseudo_bit_t owner[0x00001]; - pseudo_bit_t reserved8[0x00003]; - pseudo_bit_t opcode[0x00004]; - pseudo_bit_t reserved9[0x00008]; - pseudo_bit_t wqe_counter[0x00010]; -}; - - -/* Completion with Error CQE #### michal - gdror fixed */ - -struct shomronprm_completion_with_error_st { /* Little Endian */ - pseudo_bit_t reserved1[0x001a0]; - /* -------------- */ - pseudo_bit_t syndrome[0x00008]; - pseudo_bit_t vendor_error_syndrome[0x00008]; - pseudo_bit_t reserved2[0x00010]; - /* -------------- */ - pseudo_bit_t reserved3[0x00040]; -}; - - -struct MLX_DECLARE_STRUCT ( shomronprm_wqe_segment_ctrl_send ); -struct MLX_DECLARE_STRUCT ( shomronprm_completion_queue_entry ); -struct MLX_DECLARE_STRUCT ( shomronprm_completion_with_error ); - -struct shomron_nodnic_eth_send_wqe { - struct shomronprm_wqe_segment_ctrl_send ctrl; - struct nodnic_wqe_segment_data_ptr data[SHOMRON_MAX_GATHER]; -} __attribute__ (( packed )); - -union shomronprm_completion_entry { - struct shomronprm_completion_queue_entry normal; - struct shomronprm_completion_with_error error; -} __attribute__ (( packed )); - - -#endif /* SRC_DRIVERS_INFINIBAND_MLX_NODNIC_INCLUDE_PRM_NODNIC_SHOMRON_PRM_H_ */ diff --git a/roms/ipxe/src/drivers/infiniband/qib7322.c b/roms/ipxe/src/drivers/infiniband/qib7322.c index af7006e04..e22f2349a 100644 --- a/roms/ipxe/src/drivers/infiniband/qib7322.c +++ b/roms/ipxe/src/drivers/infiniband/qib7322.c @@ -137,21 +137,32 @@ struct qib7322 { * This card requires atomic 64-bit accesses. Strange things happen * if you try to use 32-bit accesses; sometimes they work, sometimes * they don't, sometimes you get random data. + * + * These accessors use the "movq" MMX instruction, and so won't work + * on really old Pentiums (which won't have PCIe anyway, so this is + * something of a moot point). */ /** * Read QIB7322 qword register * * @v qib7322 QIB7322 device - * @v qword Register buffer to read into + * @v dwords Register buffer to read into * @v offset Register offset */ -static void qib7322_readq ( struct qib7322 *qib7322, uint64_t *qword, +static void qib7322_readq ( struct qib7322 *qib7322, uint32_t *dwords, unsigned long offset ) { - *qword = readq ( qib7322->regs + offset ); + void *addr = ( qib7322->regs + offset ); + + __asm__ __volatile__ ( "movq (%1), %%mm0\n\t" + "movq %%mm0, (%0)\n\t" + : : "r" ( dwords ), "r" ( addr ) : "memory" ); + + DBGIO ( "[%08lx] => %08x%08x\n", + virt_to_phys ( addr ), dwords[1], dwords[0] ); } #define qib7322_readq( _qib7322, _ptr, _offset ) \ - qib7322_readq ( (_qib7322), (_ptr)->u.qwords, (_offset) ) + qib7322_readq ( (_qib7322), (_ptr)->u.dwords, (_offset) ) #define qib7322_readq_array8b( _qib7322, _ptr, _offset, _idx ) \ qib7322_readq ( (_qib7322), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) ) #define qib7322_readq_array64k( _qib7322, _ptr, _offset, _idx ) \ @@ -163,15 +174,22 @@ static void qib7322_readq ( struct qib7322 *qib7322, uint64_t *qword, * Write QIB7322 qword register * * @v qib7322 QIB7322 device - * @v qword Register buffer to write + * @v dwords Register buffer to write * @v offset Register offset */ -static void qib7322_writeq ( struct qib7322 *qib7322, const uint64_t *qword, +static void qib7322_writeq ( struct qib7322 *qib7322, const uint32_t *dwords, unsigned long offset ) { - writeq ( *qword, ( qib7322->regs + offset ) ); + void *addr = ( qib7322->regs + offset ); + + DBGIO ( "[%08lx] <= %08x%08x\n", + virt_to_phys ( addr ), dwords[1], dwords[0] ); + + __asm__ __volatile__ ( "movq (%0), %%mm0\n\t" + "movq %%mm0, (%1)\n\t" + : : "r" ( dwords ), "r" ( addr ) : "memory" ); } #define qib7322_writeq( _qib7322, _ptr, _offset ) \ - qib7322_writeq ( (_qib7322), (_ptr)->u.qwords, (_offset) ) + qib7322_writeq ( (_qib7322), (_ptr)->u.dwords, (_offset) ) #define qib7322_writeq_array8b( _qib7322, _ptr, _offset, _idx ) \ qib7322_writeq ( (_qib7322), (_ptr), ( (_offset) + ( (_idx) * 8 ) ) ) #define qib7322_writeq_array64k( _qib7322, _ptr, _offset, _idx ) \ @@ -1507,15 +1525,8 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, /* Completing the eager buffer described in * this header entry. */ - if ( payload_len <= iob_tailroom ( iobuf ) ) { - iob_put ( iobuf, payload_len ); - rc = ( err ? - -EIO : ( useegrbfr ? 0 : -ECANCELED ) ); - } else { - DBGC ( qib7322, "QIB7322 %p bad payload len " - "%zd\n", qib7322, payload_len ); - rc = -EPROTO; - } + iob_put ( iobuf, payload_len ); + rc = ( err ? -EIO : ( useegrbfr ? 0 : -ECANCELED ) ); /* Redirect to target QP if necessary */ if ( qp != intended_qp ) { DBGC2 ( qib7322, "QIB7322 %p redirecting QPN " @@ -1526,7 +1537,7 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, intended_qp->recv.fill++; } ib_complete_recv ( ibdev, intended_qp, &dest, &source, - iobuf, rc ); + iobuf, rc); } else { /* Completing on a skipped-over eager buffer */ ib_complete_recv ( ibdev, qp, &dest, &source, iobuf, @@ -2296,7 +2307,7 @@ static int qib7322_probe ( struct pci_device *pci ) { /* Fix up PCI device */ adjust_pci_device ( pci ); - /* Map PCI BARs */ + /* Get PCI BARs */ qib7322->regs = ioremap ( pci->membase, QIB7322_BAR0_SIZE ); DBGC2 ( qib7322, "QIB7322 %p has BAR at %08lx\n", qib7322, pci->membase ); @@ -2391,7 +2402,6 @@ static int qib7322_probe ( struct pci_device *pci ) { err_init_recv: err_read_eeprom: err_init_i2c: - iounmap ( qib7322->regs ); free ( qib7322 ); err_alloc_qib7322: return rc; @@ -2414,7 +2424,6 @@ static void qib7322_remove ( struct pci_device *pci ) { ibdev_put ( qib7322->ibdev[i] ); qib7322_fini_send ( qib7322 ); qib7322_fini_recv ( qib7322 ); - iounmap ( qib7322->regs ); free ( qib7322 ); } diff --git a/roms/ipxe/src/drivers/infiniband/qib7322.h b/roms/ipxe/src/drivers/infiniband/qib7322.h index dab95cfc0..72797b240 100644 --- a/roms/ipxe/src/drivers/infiniband/qib7322.h +++ b/roms/ipxe/src/drivers/infiniband/qib7322.h @@ -33,8 +33,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * */ -#define PSEUDOBIT_LITTLE_ENDIAN -#include <ipxe/pseudobit.h> +#define BITOPS_LITTLE_ENDIAN +#include <ipxe/bitops.h> #include "qib_7322_regs.h" /** A QIB7322 GPIO register */ diff --git a/roms/ipxe/src/drivers/net/3c595.c b/roms/ipxe/src/drivers/net/3c595.c index 92d38cfc5..2338c54b7 100644 --- a/roms/ipxe/src/drivers/net/3c595.c +++ b/roms/ipxe/src/drivers/net/3c595.c @@ -391,7 +391,7 @@ vxsetlink(void) { int i, j; char *reason, *warning; - static signed char prev_conn = -1; + static char prev_conn = -1; if (prev_conn == -1) { prev_conn = vx_connector; diff --git a/roms/ipxe/src/drivers/net/3c5x9.c b/roms/ipxe/src/drivers/net/3c5x9.c index d7c09f77c..4d9bc8d9e 100644 --- a/roms/ipxe/src/drivers/net/3c5x9.c +++ b/roms/ipxe/src/drivers/net/3c5x9.c @@ -108,7 +108,7 @@ static void t509_enable ( struct nic *nic ) { else if (connector == utp) { GO_WINDOW(nic->ioaddr,4); outw(ENABLE_UTP, nic->ioaddr + EP_W4_MEDIA_TYPE); - mdelay(2000); /* Give time for media to negotiate */ + sleep(2); /* Give time for media to negotiate */ GO_WINDOW(nic->ioaddr,1); } diff --git a/roms/ipxe/src/drivers/net/acm.c b/roms/ipxe/src/drivers/net/acm.c deleted file mode 100644 index 16dab4be8..000000000 --- a/roms/ipxe/src/drivers/net/acm.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <string.h> -#include <errno.h> -#include <byteswap.h> -#include <ipxe/profile.h> -#include <ipxe/usb.h> -#include <ipxe/usbnet.h> -#include <ipxe/rndis.h> -#include "acm.h" - -/** @file - * - * USB RNDIS driver - * - */ - -/** Interrupt completion profiler */ -static struct profiler acm_intr_profiler __profiler = - { .name = "acm.intr" }; - -/** Bulk IN completion profiler */ -static struct profiler acm_in_profiler __profiler = - { .name = "acm.in" }; - -/** Bulk OUT profiler */ -static struct profiler acm_out_profiler __profiler = - { .name = "acm.out" }; - -/****************************************************************************** - * - * USB RNDIS communications interface - * - ****************************************************************************** - */ - -/** - * Complete interrupt transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void acm_intr_complete ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int rc ) { - struct acm_device *acm = container_of ( ep, struct acm_device, - usbnet.intr ); - struct rndis_device *rndis = acm->rndis; - struct usb_setup_packet *message; - - /* Profile completions */ - profile_start ( &acm_intr_profiler ); - - /* Ignore packets cancelled when the endpoint closes */ - if ( ! ep->open ) - goto ignore; - - /* Drop packets with errors */ - if ( rc != 0 ) { - DBGC ( acm, "ACM %p interrupt failed: %s\n", - acm, strerror ( rc ) ); - DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) ); - goto error; - } - - /* Extract message header */ - if ( iob_len ( iobuf ) < sizeof ( *message ) ) { - DBGC ( acm, "ACM %p underlength interrupt:\n", acm ); - DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) ); - rc = -EINVAL; - goto error; - } - message = iobuf->data; - - /* Parse message header */ - switch ( message->request ) { - - case cpu_to_le16 ( CDC_RESPONSE_AVAILABLE ) : - case cpu_to_le16 ( 0x0001 ) : /* qemu seems to use this value */ - acm->responded = 1; - break; - - default: - DBGC ( acm, "ACM %p unrecognised interrupt:\n", acm ); - DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) ); - rc = -ENOTSUP; - goto error; - } - - /* Free I/O buffer */ - free_iob ( iobuf ); - profile_stop ( &acm_intr_profiler ); - - return; - - error: - rndis_rx_err ( rndis, iob_disown ( iobuf ), rc ); - ignore: - free_iob ( iobuf ); - return; -} - -/** Interrupt endpoint operations */ -static struct usb_endpoint_driver_operations acm_intr_operations = { - .complete = acm_intr_complete, -}; - -/****************************************************************************** - * - * USB RNDIS data interface - * - ****************************************************************************** - */ - -/** - * Complete bulk IN transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void acm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf, - int rc ) { - struct acm_device *acm = container_of ( ep, struct acm_device, - usbnet.in ); - struct rndis_device *rndis = acm->rndis; - - /* Profile receive completions */ - profile_start ( &acm_in_profiler ); - - /* Ignore packets cancelled when the endpoint closes */ - if ( ! ep->open ) - goto ignore; - - /* Record USB errors against the RNDIS device */ - if ( rc != 0 ) { - DBGC ( acm, "ACM %p bulk IN failed: %s\n", - acm, strerror ( rc ) ); - goto error; - } - - /* Hand off to RNDIS */ - rndis_rx ( rndis, iob_disown ( iobuf ) ); - - profile_stop ( &acm_in_profiler ); - return; - - error: - rndis_rx_err ( rndis, iob_disown ( iobuf ), rc ); - ignore: - free_iob ( iobuf ); -} - -/** Bulk IN endpoint operations */ -static struct usb_endpoint_driver_operations acm_in_operations = { - .complete = acm_in_complete, -}; - -/** - * Transmit packet - * - * @v acm USB RNDIS device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int acm_out_transmit ( struct acm_device *acm, - struct io_buffer *iobuf ) { - int rc; - - /* Profile transmissions */ - profile_start ( &acm_out_profiler ); - - /* Enqueue I/O buffer */ - if ( ( rc = usb_stream ( &acm->usbnet.out, iobuf, 0 ) ) != 0 ) - return rc; - - profile_stop ( &acm_out_profiler ); - return 0; -} - -/** - * Complete bulk OUT transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void acm_out_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf, - int rc ) { - struct acm_device *acm = container_of ( ep, struct acm_device, - usbnet.out ); - struct rndis_device *rndis = acm->rndis; - - /* Report TX completion */ - rndis_tx_complete_err ( rndis, iobuf, rc ); -} - -/** Bulk OUT endpoint operations */ -static struct usb_endpoint_driver_operations acm_out_operations = { - .complete = acm_out_complete, -}; - -/****************************************************************************** - * - * USB RNDIS control interface - * - ****************************************************************************** - */ - -/** - * Send control packet - * - * @v acm USB RNDIS device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int acm_control_transmit ( struct acm_device *acm, - struct io_buffer *iobuf ) { - struct rndis_device *rndis = acm->rndis; - struct usb_device *usb = acm->usb; - int rc; - - /* Send packet as an encapsulated command */ - if ( ( rc = cdc_send_encapsulated_command ( usb, acm->usbnet.comms, - iobuf->data, - iob_len ( iobuf ) ) ) != 0){ - DBGC ( acm, "ACM %p could not send encapsulated command: %s\n", - acm, strerror ( rc ) ); - return rc; - } - - /* Complete packet immediately */ - rndis_tx_complete ( rndis, iobuf ); - - return 0; -} - -/** - * Receive control packet - * - * @v acm USB RNDIS device - * @ret rc Return status code - */ -static int acm_control_receive ( struct acm_device *acm ) { - struct rndis_device *rndis = acm->rndis; - struct usb_device *usb = acm->usb; - struct io_buffer *iobuf; - struct rndis_header *header; - size_t mtu = ACM_RESPONSE_MTU; - size_t len; - int rc; - - /* Allocate I/O buffer */ - iobuf = alloc_iob ( mtu ); - if ( ! iobuf ) { - rc = -ENOMEM; - goto err_alloc; - } - - /* Get encapsulated response */ - if ( ( rc = cdc_get_encapsulated_response ( usb, acm->usbnet.comms, - iobuf->data, mtu ) ) != 0 ){ - DBGC ( acm, "ACM %p could not get encapsulated response: %s\n", - acm, strerror ( rc ) ); - goto err_get_response; - } - - /* Fix up buffer length */ - header = iobuf->data; - len = le32_to_cpu ( header->len ); - if ( len > mtu ) { - DBGC ( acm, "ACM %p overlength encapsulated response\n", acm ); - DBGC_HDA ( acm, 0, iobuf->data, mtu ); - rc = -EPROTO; - goto err_len; - } - iob_put ( iobuf, len ); - - /* Hand off to RNDIS */ - rndis_rx ( rndis, iob_disown ( iobuf ) ); - - return 0; - - err_len: - err_get_response: - free_iob ( iobuf ); - err_alloc: - return rc; -} - -/****************************************************************************** - * - * RNDIS interface - * - ****************************************************************************** - */ - -/** - * Open RNDIS device - * - * @v rndis RNDIS device - * @ret rc Return status code - */ -static int acm_open ( struct rndis_device *rndis ) { - struct acm_device *acm = rndis->priv; - int rc; - - /* Open USB network device */ - if ( ( rc = usbnet_open ( &acm->usbnet ) ) != 0 ) - goto err_open; - - return 0; - - usbnet_close ( &acm->usbnet ); - err_open: - return rc; -} - -/** - * Close RNDIS device - * - * @v rndis RNDIS device - */ -static void acm_close ( struct rndis_device *rndis ) { - struct acm_device *acm = rndis->priv; - - /* Close USB network device */ - usbnet_close ( &acm->usbnet ); -} - -/** - * Transmit packet - * - * @v rndis RNDIS device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int acm_transmit ( struct rndis_device *rndis, - struct io_buffer *iobuf ) { - struct acm_device *acm = rndis->priv; - struct rndis_header *header = iobuf->data; - - /* Sanity check */ - assert ( iob_len ( iobuf ) >= sizeof ( *header ) ); - assert ( iob_len ( iobuf ) == le32_to_cpu ( header->len ) ); - - /* Transmit packet via appropriate mechanism */ - if ( header->type == cpu_to_le32 ( RNDIS_PACKET_MSG ) ) { - return acm_out_transmit ( acm, iobuf ); - } else { - return acm_control_transmit ( acm, iobuf ); - } -} - -/** - * Poll for completed and received packets - * - * @v rndis RNDIS device - */ -static void acm_poll ( struct rndis_device *rndis ) { - struct acm_device *acm = rndis->priv; - int rc; - - /* Poll USB bus */ - usb_poll ( acm->bus ); - - /* Refill rings */ - if ( ( rc = usbnet_refill ( &acm->usbnet ) ) != 0 ) - rndis_rx_err ( rndis, NULL, rc ); - - /* Retrieve encapsulated response, if applicable */ - if ( acm->responded ) { - - /* Clear flag */ - acm->responded = 0; - - /* Get encapsulated response */ - if ( ( rc = acm_control_receive ( acm ) ) != 0 ) - rndis_rx_err ( rndis, NULL, rc ); - } -} - -/** USB RNDIS operations */ -static struct rndis_operations acm_operations = { - .open = acm_open, - .close = acm_close, - .transmit = acm_transmit, - .poll = acm_poll, -}; - -/****************************************************************************** - * - * USB interface - * - ****************************************************************************** - */ - -/** - * Probe device - * - * @v func USB function - * @v config Configuration descriptor - * @ret rc Return status code - */ -static int acm_probe ( struct usb_function *func, - struct usb_configuration_descriptor *config ) { - struct usb_device *usb = func->usb; - struct rndis_device *rndis; - struct acm_device *acm; - int rc; - - /* Allocate and initialise structure */ - rndis = alloc_rndis ( sizeof ( *acm ) ); - if ( ! rndis ) { - rc = -ENOMEM; - goto err_alloc; - } - rndis_init ( rndis, &acm_operations ); - rndis->netdev->dev = &func->dev; - acm = rndis->priv; - acm->usb = usb; - acm->bus = usb->port->hub->bus; - acm->rndis = rndis; - usbnet_init ( &acm->usbnet, func, &acm_intr_operations, - &acm_in_operations, &acm_out_operations ); - usb_refill_init ( &acm->usbnet.intr, 0, 0, ACM_INTR_MAX_FILL ); - usb_refill_init ( &acm->usbnet.in, 0, ACM_IN_MTU, ACM_IN_MAX_FILL ); - - /* Describe USB network device */ - if ( ( rc = usbnet_describe ( &acm->usbnet, config ) ) != 0 ) { - DBGC ( acm, "ACM %p could not describe: %s\n", - acm, strerror ( rc ) ); - goto err_describe; - } - - /* Register RNDIS device */ - if ( ( rc = register_rndis ( rndis ) ) != 0 ) - goto err_register; - - usb_func_set_drvdata ( func, acm ); - return 0; - - unregister_rndis ( rndis ); - err_register: - err_describe: - free_rndis ( rndis ); - err_alloc: - return rc; -} - -/** - * Remove device - * - * @v func USB function - */ -static void acm_remove ( struct usb_function *func ) { - struct acm_device *acm = usb_func_get_drvdata ( func ); - struct rndis_device *rndis = acm->rndis; - - /* Unregister RNDIS device */ - unregister_rndis ( rndis ); - - /* Free RNDIS device */ - free_rndis ( rndis ); -} - -/** USB CDC-ACM device IDs */ -static struct usb_device_id cdc_acm_ids[] = { - { - .name = "cdc-acm", - .vendor = USB_ANY_ID, - .product = USB_ANY_ID, - }, -}; - -/** USB CDC-ACM driver */ -struct usb_driver cdc_acm_driver __usb_driver = { - .ids = cdc_acm_ids, - .id_count = ( sizeof ( cdc_acm_ids ) / sizeof ( cdc_acm_ids[0] ) ), - .class = USB_CLASS_ID ( USB_CLASS_CDC, USB_SUBCLASS_CDC_ACM, - USB_PROTOCOL_ACM_RNDIS ), - .score = USB_SCORE_DEPRECATED, - .probe = acm_probe, - .remove = acm_remove, -}; - -/** USB RF-RNDIS device IDs */ -static struct usb_device_id rf_rndis_ids[] = { - { - .name = "rf-rndis", - .vendor = USB_ANY_ID, - .product = USB_ANY_ID, - }, -}; - -/** USB RF-RNDIS driver */ -struct usb_driver rf_rndis_driver __usb_driver = { - .ids = rf_rndis_ids, - .id_count = ( sizeof ( rf_rndis_ids ) / sizeof ( rf_rndis_ids[0] ) ), - .class = USB_CLASS_ID ( USB_CLASS_WIRELESS, USB_SUBCLASS_WIRELESS_RADIO, - USB_PROTOCOL_RADIO_RNDIS ), - .score = USB_SCORE_DEPRECATED, - .probe = acm_probe, - .remove = acm_remove, -}; diff --git a/roms/ipxe/src/drivers/net/acm.h b/roms/ipxe/src/drivers/net/acm.h deleted file mode 100644 index d4944967b..000000000 --- a/roms/ipxe/src/drivers/net/acm.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _ACM_H -#define _ACM_H - -/** @file - * - * USB RNDIS Ethernet driver - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/usb.h> -#include <ipxe/cdc.h> - -/** CDC-ACM subclass */ -#define USB_SUBCLASS_CDC_ACM 0x02 - -/** CDC-ACM RNDIS device protocol */ -#define USB_PROTOCOL_ACM_RNDIS 0xff - -/** Class code for wireless devices */ -#define USB_CLASS_WIRELESS 0xe0 - -/** Radio frequency device subclass */ -#define USB_SUBCLASS_WIRELESS_RADIO 0x01 - -/** Radio frequency RNDIS device protocol */ -#define USB_PROTOCOL_RADIO_RNDIS 0x03 - -/** A USB RNDIS network device */ -struct acm_device { - /** USB device */ - struct usb_device *usb; - /** USB bus */ - struct usb_bus *bus; - /** RNDIS device */ - struct rndis_device *rndis; - /** USB network device */ - struct usbnet_device usbnet; - - /** An encapsulated response is available */ - int responded; -}; - -/** Interrupt maximum fill level - * - * This is a policy decision. - */ -#define ACM_INTR_MAX_FILL 2 - -/** Bulk IN maximum fill level - * - * This is a policy decision. - */ -#define ACM_IN_MAX_FILL 8 - -/** Bulk IN buffer size - * - * This is a policy decision. - */ -#define ACM_IN_MTU 2048 - -/** Encapsulated response buffer size - * - * This is a policy decision. - */ -#define ACM_RESPONSE_MTU 128 - -#endif /* _ACM_H */ diff --git a/roms/ipxe/src/drivers/net/ath/ath.h b/roms/ipxe/src/drivers/net/ath/ath.h index d6a037394..42ad59f78 100644 --- a/roms/ipxe/src/drivers/net/ath/ath.h +++ b/roms/ipxe/src/drivers/net/ath/ath.h @@ -101,6 +101,8 @@ static inline u32 get_unaligned_le32(const void *p) */ #define ATH_KEYMAX 128 /* max key cache size we handle */ +static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + struct ath_ani { int caldone; unsigned int longcal_timer; @@ -227,6 +229,10 @@ struct ath_common { int btcoex_enabled; }; +struct io_buffer *ath_rxbuf_alloc(struct ath_common *common, + u32 len, + u32 *iob_addr); + void ath_hw_setbssidmask(struct ath_common *common); int ath_hw_keyreset(struct ath_common *common, u16 entry); void ath_hw_cycle_counters_update(struct ath_common *common); diff --git a/roms/ipxe/src/drivers/net/ath/ath5k/ath5k.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k.c index a6a65a2e9..92c4ffdf4 100644 --- a/roms/ipxe/src/drivers/net/ath/ath5k/ath5k.c +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k.c @@ -85,6 +85,46 @@ static struct pci_device_id ath5k_nics[] = { PCI_ROM(0x168c, 0x001d, "ath2417", "Atheros 2417 Nala", AR5K_AR5212), }; +/* Known SREVs */ +static const struct ath5k_srev_name srev_names[] = { + { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, + { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, + { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, + { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B }, + { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 }, + { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 }, + { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 }, + { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A }, + { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 }, + { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 }, + { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 }, + { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 }, + { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 }, + { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 }, + { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 }, + { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, + { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, + { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, + { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, + { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, + { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, + { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A }, + { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 }, + { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 }, + { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A }, + { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B }, + { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 }, + { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A }, + { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, + { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, + { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, + { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, + { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, + { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, + { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, + { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, +}; + #define ATH5K_SPMBL_NO 1 #define ATH5K_SPMBL_YES 2 #define ATH5K_SPMBL_BOTH 3 diff --git a/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c index c2a66a4d3..7891d39ea 100644 --- a/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_phy.c @@ -1219,12 +1219,12 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, /* Update radio registers */ ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) | - AR5K_REG_SM(-1U, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG); + AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG); ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI | AR5K_PHY_AGCCOARSE_LO)) | - AR5K_REG_SM(-1U, AR5K_PHY_AGCCOARSE_HI) | - AR5K_REG_SM(-127U, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE); + AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) | + AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE); ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT | AR5K_PHY_ADCSAT_THR)) | diff --git a/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c index 73765a7b0..2f36a4e9a 100644 --- a/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c +++ b/roms/ipxe/src/drivers/net/ath/ath5k/ath5k_reset.c @@ -134,6 +134,14 @@ static int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, return 0; } + +/* + * index into rates for control rates, we can set it up like this because + * this is only used for AR5212 and we know it supports G mode + */ +static const unsigned int control_rates[] = + { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; + /** * ath5k_hw_write_rate_duration - fill rate code to duration table * diff --git a/roms/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h index f9a92c9b7..d7a5ac09f 100644 --- a/roms/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h +++ b/roms/ipxe/src/drivers/net/ath/ath9k/ar9002_initvals.h @@ -16,7 +16,7 @@ FILE_LICENCE ( BSD2 ); -static __unused const u32 ar9280Modes_9280_2[][6] = { +static const u32 ar9280Modes_9280_2[][6] = { {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, @@ -65,7 +65,7 @@ static __unused const u32 ar9280Modes_9280_2[][6] = { {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000}, }; -static __unused const u32 ar9280Common_9280_2[][2] = { +static const u32 ar9280Common_9280_2[][2] = { /* Addr allmodes */ {0x0000000c, 0x00000000}, {0x00000030, 0x00020015}, @@ -409,7 +409,7 @@ static __unused const u32 ar9280Common_9280_2[][2] = { {0x00007898, 0x2a850160}, }; -static __unused const u32 ar9280Modes_fast_clock_9280_2[][3] = { +static const u32 ar9280Modes_fast_clock_9280_2[][3] = { /* Addr 5G_HT20 5G_HT40 */ {0x00001030, 0x00000268, 0x000004d0}, {0x00001070, 0x0000018c, 0x00000318}, @@ -426,7 +426,7 @@ static __unused const u32 ar9280Modes_fast_clock_9280_2[][3] = { {0x00009918, 0x0000000b, 0x00000016}, }; -static __unused const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { +static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290}, {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300}, {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304}, @@ -559,7 +559,7 @@ static __unused const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { {0x0000a848, 0x00001066, 0x00001066, 0x00001055, 0x00001055, 0x00001055}, }; -static __unused const u32 ar9280Modes_original_rxgain_9280_2[][6] = { +static const u32 ar9280Modes_original_rxgain_9280_2[][6] = { {0x00009a00, 0x00008184, 0x00008184, 0x00008000, 0x00008000, 0x00008000}, {0x00009a04, 0x00008188, 0x00008188, 0x00008000, 0x00008000, 0x00008000}, {0x00009a08, 0x0000818c, 0x0000818c, 0x00008000, 0x00008000, 0x00008000}, @@ -692,7 +692,7 @@ static __unused const u32 ar9280Modes_original_rxgain_9280_2[][6] = { {0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063}, }; -static __unused const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { +static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { {0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290}, {0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300}, {0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304}, @@ -825,7 +825,7 @@ static __unused const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { {0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a}, }; -static __unused const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { +static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { {0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652}, {0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce}, {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -859,7 +859,7 @@ static __unused const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { {0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480}, }; -static __unused const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { +static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { {0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652}, {0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce}, {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -893,7 +893,7 @@ static __unused const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { {0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480}, }; -static __unused const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { +static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { /* Addr allmodes */ {0x00004040, 0x9248fd00}, {0x00004040, 0x24924924}, @@ -907,7 +907,7 @@ static __unused const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { {0x00004044, 0x00000000}, }; -static __unused const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { +static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { /* Addr allmodes */ {0x00004040, 0x9248fd00}, {0x00004040, 0x24924924}, @@ -921,7 +921,7 @@ static __unused const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { {0x00004044, 0x00000000}, }; -static __unused const u32 ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { +static const u32 ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { /* Addr allmodes */ {0x00004040, 0x9248fd00}, {0x00004040, 0x24924924}, @@ -935,7 +935,7 @@ static __unused const u32 ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { {0x00004044, 0x00000000}, }; -static __unused const u32 ar9285PciePhy_clkreq_off_L1_9285[][2] = { +static const u32 ar9285PciePhy_clkreq_off_L1_9285[][2] = { /* Addr allmodes */ {0x00004040, 0x9248fd00}, {0x00004040, 0x24924924}, @@ -949,7 +949,7 @@ static __unused const u32 ar9285PciePhy_clkreq_off_L1_9285[][2] = { {0x00004044, 0x00000000}, }; -static __unused const u32 ar9285Modes_9285_1_2[][6] = { +static const u32 ar9285Modes_9285_1_2[][6] = { {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, @@ -1254,7 +1254,7 @@ static __unused const u32 ar9285Modes_9285_1_2[][6] = { {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e}, }; -static __unused const u32 ar9285Common_9285_1_2[][2] = { +static const u32 ar9285Common_9285_1_2[][2] = { /* Addr allmodes */ {0x0000000c, 0x00000000}, {0x00000030, 0x00020045}, @@ -1574,7 +1574,7 @@ static __unused const u32 ar9285Common_9285_1_2[][2] = { {0x00007870, 0x10142c00}, }; -static __unused const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { +static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000}, {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000}, @@ -1614,7 +1614,7 @@ static __unused const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7}, }; -static __unused const u32 ar9285Modes_original_tx_gain_9285_1_2[][6] = { +static const u32 ar9285Modes_original_tx_gain_9285_1_2[][6] = { {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000}, {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000}, @@ -1654,7 +1654,7 @@ static __unused const u32 ar9285Modes_original_tx_gain_9285_1_2[][6] = { {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c}, }; -static __unused const u32 ar9285Modes_XE2_0_normal_power[][6] = { +static const u32 ar9285Modes_XE2_0_normal_power[][6] = { {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000}, {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000}, @@ -1694,7 +1694,7 @@ static __unused const u32 ar9285Modes_XE2_0_normal_power[][6] = { {0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c}, }; -static __unused const u32 ar9285Modes_XE2_0_high_power[][6] = { +static const u32 ar9285Modes_XE2_0_high_power[][6] = { {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000}, {0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000}, @@ -1734,7 +1734,7 @@ static __unused const u32 ar9285Modes_XE2_0_high_power[][6] = { {0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7}, }; -static __unused const u32 ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { +static const u32 ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { /* Addr allmodes */ {0x00004040, 0x9248fd00}, {0x00004040, 0x24924924}, @@ -1748,7 +1748,7 @@ static __unused const u32 ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { {0x00004044, 0x00000000}, }; -static __unused const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { +static const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { /* Addr allmodes */ {0x00004040, 0x9248fd00}, {0x00004040, 0x24924924}, @@ -1762,7 +1762,7 @@ static __unused const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { {0x00004044, 0x00000000}, }; -static __unused const u32 ar9287Modes_9287_1_1[][6] = { +static const u32 ar9287Modes_9287_1_1[][6] = { {0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0}, {0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0}, {0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180}, @@ -1808,7 +1808,7 @@ static __unused const u32 ar9287Modes_9287_1_1[][6] = { {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, }; -static __unused const u32 ar9287Common_9287_1_1[][2] = { +static const u32 ar9287Common_9287_1_1[][2] = { /* Addr allmodes */ {0x0000000c, 0x00000000}, {0x00000030, 0x00020015}, @@ -2177,21 +2177,21 @@ static __unused const u32 ar9287Common_9287_1_1[][2] = { {0x000078b8, 0x2a850160}, }; -static __unused const u32 ar9287Common_normal_cck_fir_coeff_9287_1_1[][2] = { +static const u32 ar9287Common_normal_cck_fir_coeff_9287_1_1[][2] = { /* Addr allmodes */ {0x0000a1f4, 0x00fffeff}, {0x0000a1f8, 0x00f5f9ff}, {0x0000a1fc, 0xb79f6427}, }; -static __unused const u32 ar9287Common_japan_2484_cck_fir_coeff_9287_1_1[][2] = { +static const u32 ar9287Common_japan_2484_cck_fir_coeff_9287_1_1[][2] = { /* Addr allmodes */ {0x0000a1f4, 0x00000000}, {0x0000a1f8, 0xefff0301}, {0x0000a1fc, 0xca9228ee}, }; -static __unused const u32 ar9287Modes_tx_gain_9287_1_1[][6] = { +static const u32 ar9287Modes_tx_gain_9287_1_1[][6] = { {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002}, {0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004}, @@ -2239,7 +2239,7 @@ static __unused const u32 ar9287Modes_tx_gain_9287_1_1[][6] = { {0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000}, }; -static __unused const u32 ar9287Modes_rx_gain_9287_1_1[][6] = { +static const u32 ar9287Modes_rx_gain_9287_1_1[][6] = { {0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120}, {0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124}, {0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128}, @@ -2500,7 +2500,7 @@ static __unused const u32 ar9287Modes_rx_gain_9287_1_1[][6] = { {0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067}, }; -static __unused const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { +static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { /* Addr allmodes */ {0x00004040, 0x9248fd00}, {0x00004040, 0x24924924}, @@ -2514,7 +2514,7 @@ static __unused const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { {0x00004044, 0x00000000}, }; -static __unused const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { +static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { /* Addr allmodes */ {0x00004040, 0x9248fd00}, {0x00004040, 0x24924924}, @@ -2528,7 +2528,7 @@ static __unused const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { {0x00004044, 0x00000000}, }; -static __unused const u32 ar9271Modes_9271[][6] = { +static const u32 ar9271Modes_9271[][6] = { {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0}, {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0}, {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180}, @@ -2834,7 +2834,7 @@ static __unused const u32 ar9271Modes_9271[][6] = { {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e}, }; -static __unused const u32 ar9271Common_9271[][2] = { +static const u32 ar9271Common_9271[][2] = { /* Addr allmodes */ {0x0000000c, 0x00000000}, {0x00000030, 0x00020045}, @@ -3163,26 +3163,26 @@ static __unused const u32 ar9271Common_9271[][2] = { {0x0000d384, 0xf3307ff0}, }; -static __unused const u32 ar9271Common_normal_cck_fir_coeff_9271[][2] = { +static const u32 ar9271Common_normal_cck_fir_coeff_9271[][2] = { /* Addr allmodes */ {0x0000a1f4, 0x00fffeff}, {0x0000a1f8, 0x00f5f9ff}, {0x0000a1fc, 0xb79f6427}, }; -static __unused const u32 ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = { +static const u32 ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = { /* Addr allmodes */ {0x0000a1f4, 0x00000000}, {0x0000a1f8, 0xefff0301}, {0x0000a1fc, 0xca9228ee}, }; -static __unused const u32 ar9271Modes_9271_1_0_only[][6] = { +static const u32 ar9271Modes_9271_1_0_only[][6] = { {0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311}, {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001}, }; -static __unused const u32 ar9271Modes_9271_ANI_reg[][6] = { +static const u32 ar9271Modes_9271_ANI_reg[][6] = { {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2}, {0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e}, {0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e}, @@ -3193,7 +3193,7 @@ static __unused const u32 ar9271Modes_9271_ANI_reg[][6] = { {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, }; -static __unused const u32 ar9271Modes_normal_power_tx_gain_9271[][6] = { +static const u32 ar9271Modes_normal_power_tx_gain_9271[][6] = { {0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000}, {0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000}, @@ -3229,7 +3229,7 @@ static __unused const u32 ar9271Modes_normal_power_tx_gain_9271[][6] = { {0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd}, }; -static __unused const u32 ar9271Modes_high_power_tx_gain_9271[][6] = { +static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = { {0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000}, {0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000}, {0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000}, diff --git a/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h index b1303bbaa..e8ac70da5 100644 --- a/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h +++ b/roms/ipxe/src/drivers/net/ath/ath9k/ar9003_2p2_initvals.h @@ -19,7 +19,7 @@ /* AR9003 2.2 */ -static __unused const u32 ar9300_2p2_radio_postamble[][5] = { +static const u32 ar9300_2p2_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, @@ -32,7 +32,7 @@ static __unused const u32 ar9300_2p2_radio_postamble[][5] = { {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, }; -static __unused const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { +static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, @@ -138,7 +138,7 @@ static __unused const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -static __unused const u32 ar9300Modes_fast_clock_2p2[][3] = { +static const u32 ar9300Modes_fast_clock_2p2[][3] = { /* Addr 5G_HT20 5G_HT40 */ {0x00001030, 0x00000268, 0x000004d0}, {0x00001070, 0x0000018c, 0x00000318}, @@ -151,7 +151,7 @@ static __unused const u32 ar9300Modes_fast_clock_2p2[][3] = { {0x0000a254, 0x00000898, 0x00001130}, }; -static __unused const u32 ar9300_2p2_radio_core[][2] = { +static const u32 ar9300_2p2_radio_core[][2] = { /* Addr allmodes */ {0x00016000, 0x36db6db6}, {0x00016004, 0x6db6db40}, @@ -295,7 +295,7 @@ static __unused const u32 ar9300_2p2_radio_core[][2] = { {0x00016bd4, 0x00000000}, }; -static __unused const u32 ar9300Common_rx_gain_table_merlin_2p2[][2] = { +static const u32 ar9300Common_rx_gain_table_merlin_2p2[][2] = { /* Addr allmodes */ {0x0000a000, 0x02000101}, {0x0000a004, 0x02000102}, @@ -555,7 +555,7 @@ static __unused const u32 ar9300Common_rx_gain_table_merlin_2p2[][2] = { {0x0000b1fc, 0x00000776}, }; -static __unused const u32 ar9300_2p2_mac_postamble[][5] = { +static const u32 ar9300_2p2_mac_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, @@ -567,12 +567,12 @@ static __unused const u32 ar9300_2p2_mac_postamble[][5] = { {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, }; -static __unused const u32 ar9300_2p2_soc_postamble[][5] = { +static const u32 ar9300_2p2_soc_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, }; -static __unused const u32 ar9200_merlin_2p2_radio_core[][2] = { +static const u32 ar9200_merlin_2p2_radio_core[][2] = { /* Addr allmodes */ {0x00007800, 0x00040000}, {0x00007804, 0xdb005012}, @@ -614,7 +614,7 @@ static __unused const u32 ar9200_merlin_2p2_radio_core[][2] = { {0x00007894, 0x5a108000}, }; -static __unused const u32 ar9300_2p2_baseband_postamble[][5] = { +static const u32 ar9300_2p2_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, @@ -670,7 +670,7 @@ static __unused const u32 ar9300_2p2_baseband_postamble[][5] = { {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, }; -static __unused const u32 ar9300_2p2_baseband_core[][2] = { +static const u32 ar9300_2p2_baseband_core[][2] = { /* Addr allmodes */ {0x00009800, 0xafe68e30}, {0x00009804, 0xfd14e000}, @@ -833,7 +833,7 @@ static __unused const u32 ar9300_2p2_baseband_core[][2] = { {0x0000c420, 0x00000000}, }; -static __unused const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { +static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, @@ -939,7 +939,7 @@ static __unused const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, }; -static __unused const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { +static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, @@ -1045,7 +1045,7 @@ static __unused const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -static __unused const u32 ar9300Common_rx_gain_table_2p2[][2] = { +static const u32 ar9300Common_rx_gain_table_2p2[][2] = { /* Addr allmodes */ {0x0000a000, 0x00010000}, {0x0000a004, 0x00030002}, @@ -1305,7 +1305,7 @@ static __unused const u32 ar9300Common_rx_gain_table_2p2[][2] = { {0x0000b1fc, 0x00000196}, }; -static __unused const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { +static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, @@ -1411,7 +1411,7 @@ static __unused const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; -static __unused const u32 ar9300_2p2_mac_core[][2] = { +static const u32 ar9300_2p2_mac_core[][2] = { /* Addr allmodes */ {0x00000008, 0x00000000}, {0x00000030, 0x00020085}, @@ -1570,7 +1570,7 @@ static __unused const u32 ar9300_2p2_mac_core[][2] = { {0x000083d0, 0x000301ff}, }; -static __unused const u32 ar9300Common_wo_xlna_rx_gain_table_2p2[][2] = { +static const u32 ar9300Common_wo_xlna_rx_gain_table_2p2[][2] = { /* Addr allmodes */ {0x0000a000, 0x00010000}, {0x0000a004, 0x00030002}, @@ -1830,7 +1830,7 @@ static __unused const u32 ar9300Common_wo_xlna_rx_gain_table_2p2[][2] = { {0x0000b1fc, 0x00000196}, }; -static __unused const u32 ar9300_2p2_soc_preamble[][2] = { +static const u32 ar9300_2p2_soc_preamble[][2] = { /* Addr allmodes */ {0x000040a4, 0x00a0c1c9}, {0x00007008, 0x00000000}, @@ -1840,21 +1840,21 @@ static __unused const u32 ar9300_2p2_soc_preamble[][2] = { {0x00007048, 0x00000008}, }; -static __unused const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = { +static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = { /* Addr allmodes */ {0x00004040, 0x0821265e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; -static __unused const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = { +static const u32 ar9300PciePhy_clkreq_enable_L1_2p2[][2] = { /* Addr allmodes */ {0x00004040, 0x08253e5e}, {0x00004040, 0x0008003b}, {0x00004044, 0x00000000}, }; -static __unused const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = { +static const u32 ar9300PciePhy_clkreq_disable_L1_2p2[][2] = { /* Addr allmodes */ {0x00004040, 0x08213e5e}, {0x00004040, 0x0008003b}, diff --git a/roms/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h index 784080b16..815a8af1b 100644 --- a/roms/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h +++ b/roms/ipxe/src/drivers/net/ath/ath9k/ar9340_initvals.h @@ -17,7 +17,7 @@ #ifndef INITVALS_9340_H #define INITVALS_9340_H -static __unused const u32 ar9340_1p0_radio_postamble[][5] = { +static const u32 ar9340_1p0_radio_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800}, {0x0001610c, 0x08000000, 0x08000000, 0x00000000, 0x00000000}, @@ -26,7 +26,7 @@ static __unused const u32 ar9340_1p0_radio_postamble[][5] = { {0x00016540, 0x10804000, 0x10804000, 0x50804000, 0x50804000}, }; -static __unused const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = { +static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -99,7 +99,7 @@ static __unused const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = { {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, }; -static __unused const u32 ar9340Modes_fast_clock_1p0[][3] = { +static const u32 ar9340Modes_fast_clock_1p0[][3] = { /* Addr 5G_HT20 5G_HT40 */ {0x00001030, 0x00000268, 0x000004d0}, {0x00001070, 0x0000018c, 0x00000318}, @@ -112,7 +112,7 @@ static __unused const u32 ar9340Modes_fast_clock_1p0[][3] = { {0x0000a254, 0x00000898, 0x00001130}, }; -static __unused const u32 ar9340_1p0_radio_core[][2] = { +static const u32 ar9340_1p0_radio_core[][2] = { /* Addr allmodes */ {0x00016000, 0x36db6db6}, {0x00016004, 0x6db6db40}, @@ -218,13 +218,13 @@ static __unused const u32 ar9340_1p0_radio_core[][2] = { {0x000167d4, 0x00000000}, }; -static __unused const u32 ar9340_1p0_radio_core_40M[][2] = { +static const u32 ar9340_1p0_radio_core_40M[][2] = { {0x0001609c, 0x02566f3a}, {0x000160ac, 0xa4647c00}, {0x000160b0, 0x01885f5a}, }; -static __unused const u32 ar9340_1p0_mac_postamble[][5] = { +static const u32 ar9340_1p0_mac_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, @@ -236,12 +236,12 @@ static __unused const u32 ar9340_1p0_mac_postamble[][5] = { {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, }; -static __unused const u32 ar9340_1p0_soc_postamble[][5] = { +static const u32 ar9340_1p0_soc_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, }; -static __unused const u32 ar9340_1p0_baseband_postamble[][5] = { +static const u32 ar9340_1p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e}, @@ -288,7 +288,7 @@ static __unused const u32 ar9340_1p0_baseband_postamble[][5] = { {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, }; -static __unused const u32 ar9340_1p0_baseband_core[][2] = { +static const u32 ar9340_1p0_baseband_core[][2] = { /* Addr allmodes */ {0x00009800, 0xafe68e30}, {0x00009804, 0xfd14e000}, @@ -464,7 +464,7 @@ static __unused const u32 ar9340_1p0_baseband_core[][2] = { {0x0000b420, 0x00000000}, }; -static __unused const u32 ar9340Modes_high_power_tx_gain_table_1p0[][5] = { +static const u32 ar9340Modes_high_power_tx_gain_table_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, @@ -537,7 +537,7 @@ static __unused const u32 ar9340Modes_high_power_tx_gain_table_1p0[][5] = { {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, }; -static __unused const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = { +static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, @@ -609,7 +609,7 @@ static __unused const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = { {0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4}, {0x00016448, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266}, }; -static __unused const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = { +static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, @@ -683,7 +683,7 @@ static __unused const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = { }; -static __unused const u32 ar9340Common_rx_gain_table_1p0[][2] = { +static const u32 ar9340Common_rx_gain_table_1p0[][2] = { /* Addr allmodes */ {0x0000a000, 0x00010000}, {0x0000a004, 0x00030002}, @@ -943,7 +943,7 @@ static __unused const u32 ar9340Common_rx_gain_table_1p0[][2] = { {0x0000b1fc, 0x00000196}, }; -static __unused const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = { +static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -1016,7 +1016,7 @@ static __unused const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = { {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, }; -static __unused const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = { +static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -1089,7 +1089,7 @@ static __unused const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = { {0x00016448, 0x24927266, 0x24927266, 0x8e482266, 0x8e482266}, }; -static __unused const u32 ar9340_1p0_mac_core[][2] = { +static const u32 ar9340_1p0_mac_core[][2] = { /* Addr allmodes */ {0x00000008, 0x00000000}, {0x00000030, 0x00020085}, @@ -1253,7 +1253,7 @@ static __unused const u32 ar9340_1p0_mac_core[][2] = { {0x000083d0, 0x000301ff}, }; -static __unused const u32 ar9340Common_wo_xlna_rx_gain_table_1p0[][2] = { +static const u32 ar9340Common_wo_xlna_rx_gain_table_1p0[][2] = { /* Addr allmodes */ {0x0000a000, 0x00010000}, {0x0000a004, 0x00030002}, @@ -1513,7 +1513,7 @@ static __unused const u32 ar9340Common_wo_xlna_rx_gain_table_1p0[][2] = { {0x0000b1fc, 0x00000196}, }; -static __unused const u32 ar9340_1p0_soc_preamble[][2] = { +static const u32 ar9340_1p0_soc_preamble[][2] = { /* Addr allmodes */ {0x000040a4, 0x00a0c1c9}, {0x00007008, 0x00000000}, diff --git a/roms/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h b/roms/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h index c854398aa..611ea6ce8 100644 --- a/roms/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h +++ b/roms/ipxe/src/drivers/net/ath/ath9k/ar9485_initvals.h @@ -17,7 +17,7 @@ #ifndef INITVALS_9485_H #define INITVALS_9485_H -static __unused const u32 ar9485_1_1_mac_core[][2] = { +static const u32 ar9485_1_1_mac_core[][2] = { /* Addr allmodes */ {0x00000008, 0x00000000}, {0x00000030, 0x00020085}, @@ -179,7 +179,7 @@ static __unused const u32 ar9485_1_1_mac_core[][2] = { {0x000083d0, 0x000301ff}, }; -static __unused const u32 ar9485_1_1_baseband_core[][2] = { +static const u32 ar9485_1_1_baseband_core[][2] = { /* Addr allmodes */ {0x00009800, 0xafe68e30}, {0x00009804, 0xfd14e000}, @@ -316,7 +316,7 @@ static __unused const u32 ar9485_1_1_baseband_core[][2] = { {0x0000a7dc, 0x00000000}, }; -static __unused const u32 ar9485Common_1_1[][2] = { +static const u32 ar9485Common_1_1[][2] = { /* Addr allmodes */ {0x00007010, 0x00000022}, {0x00007020, 0x00000000}, @@ -324,7 +324,7 @@ static __unused const u32 ar9485Common_1_1[][2] = { {0x00007038, 0x000004c2}, }; -static __unused const u32 ar9485_1_1_baseband_postamble[][5] = { +static const u32 ar9485_1_1_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e}, @@ -369,7 +369,7 @@ static __unused const u32 ar9485_1_1_baseband_postamble[][5] = { {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, }; -static __unused const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { +static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, @@ -442,7 +442,7 @@ static __unused const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, }; -static __unused const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = { +static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, @@ -515,7 +515,7 @@ static __unused const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = { {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, }; -static __unused const u32 ar9485_1_1_radio_postamble[][2] = { +static const u32 ar9485_1_1_radio_postamble[][2] = { /* Addr allmodes */ {0x0001609c, 0x0b283f31}, {0x000160ac, 0x24611800}, @@ -524,7 +524,7 @@ static __unused const u32 ar9485_1_1_radio_postamble[][2] = { {0x00016140, 0x10804008}, }; -static __unused const u32 ar9485_1_1_mac_postamble[][5] = { +static const u32 ar9485_1_1_mac_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, @@ -536,7 +536,7 @@ static __unused const u32 ar9485_1_1_mac_postamble[][5] = { {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, }; -static __unused const u32 ar9485_1_1_radio_core[][2] = { +static const u32 ar9485_1_1_radio_core[][2] = { /* Addr allmodes */ {0x00016000, 0x36db6db6}, {0x00016004, 0x6db6db40}, @@ -601,14 +601,14 @@ static __unused const u32 ar9485_1_1_radio_core[][2] = { {0x00016c44, 0x12000000}, }; -static __unused const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = { +static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = { /* Addr allmodes */ {0x00018c00, 0x10052e5e}, {0x00018c04, 0x000801d8}, {0x00018c08, 0x0000080c}, }; -static __unused const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { +static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, @@ -681,7 +681,7 @@ static __unused const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, }; -static __unused const u32 ar9485_1_1[][2] = { +static const u32 ar9485_1_1[][2] = { /* Addr allmodes */ {0x0000a580, 0x00000000}, {0x0000a584, 0x00000000}, @@ -701,7 +701,7 @@ static __unused const u32 ar9485_1_1[][2] = { {0x0000a5bc, 0x00000000}, }; -static __unused const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = { +static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, @@ -774,14 +774,14 @@ static __unused const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = { {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, }; -static __unused const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = { +static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = { /* Addr allmodes */ {0x00018c00, 0x10013e5e}, {0x00018c04, 0x000801d8}, {0x00018c08, 0x0000080c}, }; -static __unused const u32 ar9485_1_1_soc_preamble[][2] = { +static const u32 ar9485_1_1_soc_preamble[][2] = { /* Addr allmodes */ {0x00004014, 0xba280400}, {0x00004090, 0x00aa10aa}, @@ -793,14 +793,14 @@ static __unused const u32 ar9485_1_1_soc_preamble[][2] = { {0x00007048, 0x00000002}, }; -static __unused const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = { +static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = { /* Addr allmodes */ {0x0000a398, 0x00000000}, {0x0000a39c, 0x6f7f0301}, {0x0000a3a0, 0xca9228ee}, }; -static __unused const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { +static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, @@ -873,21 +873,21 @@ static __unused const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, }; -static __unused const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = { +static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = { /* Addr 5G_HT2 5G_HT40 */ {0x00009e00, 0x03721821, 0x03721821}, {0x0000a230, 0x0000400b, 0x00004016}, {0x0000a254, 0x00000898, 0x00001130}, }; -static __unused const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = { +static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = { /* Addr allmodes */ {0x00018c00, 0x10012e5e}, {0x00018c04, 0x000801d8}, {0x00018c08, 0x0000080c}, }; -static __unused const u32 ar9485_common_rx_gain_1_1[][2] = { +static const u32 ar9485_common_rx_gain_1_1[][2] = { /* Addr allmodes */ {0x0000a000, 0x00010000}, {0x0000a004, 0x00030002}, @@ -1019,14 +1019,14 @@ static __unused const u32 ar9485_common_rx_gain_1_1[][2] = { {0x0000a1fc, 0x00000296}, }; -static __unused const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = { +static const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = { /* Addr allmodes */ {0x00018c00, 0x10053e5e}, {0x00018c04, 0x000801d8}, {0x00018c08, 0x0000080c}, }; -static __unused const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = { +static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = { /* Addr allmodes */ {0x0000a000, 0x00060005}, {0x0000a004, 0x00810080}, diff --git a/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c index a20423790..f552acaa3 100644 --- a/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c +++ b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_eeprom.c @@ -368,9 +368,10 @@ void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah, if (match) { if (AR_SREV_9287(ah)) { + /* FIXME: array overrun? */ for (i = 0; i < numXpdGains; i++) { minPwrT4[i] = data_9287[idxL].pwrPdg[i][0]; - maxPwrT4[i] = data_9287[idxL].pwrPdg[i][intercepts - 1]; + maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4]; ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], data_9287[idxL].pwrPdg[i], data_9287[idxL].vpdPdg[i], @@ -380,7 +381,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah, } else if (eeprom_4k) { for (i = 0; i < numXpdGains; i++) { minPwrT4[i] = data_4k[idxL].pwrPdg[i][0]; - maxPwrT4[i] = data_4k[idxL].pwrPdg[i][intercepts - 1]; + maxPwrT4[i] = data_4k[idxL].pwrPdg[i][4]; ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], data_4k[idxL].pwrPdg[i], data_4k[idxL].vpdPdg[i], @@ -390,7 +391,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah, } else { for (i = 0; i < numXpdGains; i++) { minPwrT4[i] = data_def[idxL].pwrPdg[i][0]; - maxPwrT4[i] = data_def[idxL].pwrPdg[i][intercepts - 1]; + maxPwrT4[i] = data_def[idxL].pwrPdg[i][4]; ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], data_def[idxL].pwrPdg[i], data_def[idxL].vpdPdg[i], diff --git a/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c index 98a0d6d59..03de7701a 100644 --- a/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c +++ b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_init.c @@ -22,7 +22,6 @@ FILE_LICENCE ( BSD2 ); #include <ipxe/malloc.h> #include <ipxe/pci_io.h> #include <ipxe/pci.h> -#include <ipxe/ethernet.h> #include "ath9k.h" @@ -350,7 +349,7 @@ static void ath9k_init_misc(struct ath_softc *sc) ath9k_hw_set_diversity(sc->sc_ah, 1); sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); - memcpy(common->bssidmask, eth_broadcast, ETH_ALEN); + memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); } static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, diff --git a/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c index 0ffe9d45a..ba363c676 100644 --- a/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c +++ b/roms/ipxe/src/drivers/net/ath/ath9k/ath9k_recv.c @@ -98,6 +98,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct io_buffer *iob; + u32 *iob_addr = NULL; struct ath_buf *bf; int error = 0; @@ -121,14 +122,15 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) } list_for_each_entry(bf, &sc->rx.rxbuf, list) { - iob = alloc_iob_raw ( common->rx_bufsize, common->cachelsz, 0 ); + iob = ath_rxbuf_alloc(common, common->rx_bufsize, + iob_addr); if (iob == NULL) { error = -ENOMEM; goto err; } bf->bf_mpdu = iob; - bf->bf_buf_addr = virt_to_bus ( iob->data ); + bf->bf_buf_addr = *iob_addr; } sc->rx.rxlink = NULL; @@ -431,6 +433,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, int hp __unused) { struct ath_buf *bf; struct io_buffer *iob = NULL, *requeue_iob; + u32 *requeue_iob_addr = NULL; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); /* @@ -473,8 +476,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, int hp __unused) /* Ensure we always have an iob to requeue once we are done * processing the current buffer's iob */ - requeue_iob = alloc_iob_raw ( common->rx_bufsize, - common->cachelsz, 0 ); + requeue_iob = ath_rxbuf_alloc(common, common->rx_bufsize, requeue_iob_addr); /* If there is no memory we ignore the current RX'd frame, * tell hardware it can give us a new frame using the old @@ -489,7 +491,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, int hp __unused) /* We will now give hardware our shiny new allocated iob */ bf->bf_mpdu = requeue_iob; - bf->bf_buf_addr = virt_to_bus ( requeue_iob->data ); + bf->bf_buf_addr = *requeue_iob_addr; /* * change the default rx antenna if rx diversity chooses the diff --git a/roms/ipxe/src/drivers/net/ath/ath_main.c b/roms/ipxe/src/drivers/net/ath/ath_main.c new file mode 100644 index 000000000..85d159a36 --- /dev/null +++ b/roms/ipxe/src/drivers/net/ath/ath_main.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2009 Atheros Communications Inc. + * + * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011 + * Original from Linux kernel 3.0.1 + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <ipxe/io.h> + +#include "ath.h" + +struct io_buffer *ath_rxbuf_alloc(struct ath_common *common, + u32 len, + u32 *iob_addr) +{ + struct io_buffer *iob; + u32 off; + + /* + * Cache-line-align. This is important (for the + * 5210 at least) as not doing so causes bogus data + * in rx'd frames. + */ + + /* Note: the kernel can allocate a value greater than + * what we ask it to give us. We really only need 4 KB as that + * is this hardware supports and in fact we need at least 3849 + * as that is the MAX AMSDU size this hardware supports. + * Unfortunately this means we may get 8 KB here from the + * kernel... and that is actually what is observed on some + * systems :( */ + iob = alloc_iob(len + common->cachelsz - 1); + if (iob != NULL) { + *iob_addr = virt_to_bus(iob->data); + off = ((unsigned long) iob->data) % common->cachelsz; + if (off != 0) + { + iob_reserve(iob, common->cachelsz - off); + *iob_addr += common->cachelsz - off; + } + } else { + DBG("ath: iobuffer alloc of size %d failed\n", len); + return NULL; + } + + return iob; +} diff --git a/roms/ipxe/src/drivers/net/axge.c b/roms/ipxe/src/drivers/net/axge.c deleted file mode 100644 index ab59a8be7..000000000 --- a/roms/ipxe/src/drivers/net/axge.c +++ /dev/null @@ -1,798 +0,0 @@ -/* - * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <ipxe/netdevice.h> -#include <ipxe/ethernet.h> -#include <ipxe/if_ether.h> -#include <ipxe/profile.h> -#include <ipxe/usb.h> -#include "axge.h" - -/** @file - * - * Asix 10/100/1000 USB Ethernet driver - * - * Large chunks of functionality are undocumented in the available - * datasheets. The gaps are deduced from combinations of the Linux - * driver, the FreeBSD driver, and experimentation with the hardware. - */ - -/** Interrupt completion profiler */ -static struct profiler axge_intr_profiler __profiler = - { .name = "axge.intr" }; - -/** Bulk IN completion profiler */ -static struct profiler axge_in_profiler __profiler = - { .name = "axge.in" }; - -/** Bulk OUT profiler */ -static struct profiler axge_out_profiler __profiler = - { .name = "axge.out" }; - -/** Default bulk IN configuration - * - * The Linux and FreeBSD drivers have set of magic constants which are - * chosen based on both the Ethernet and USB link speeds. - * - * Experimentation shows that setting the "timer" value to zero seems - * to prevent the device from ever coalescing multiple packets into a - * single bulk IN transfer. This allows us to get away with using a - * 2kB receive I/O buffer and a zerocopy receive path. - */ -static struct axge_bulk_in_control axge_bicr = { - .ctrl = 7, - .timer = cpu_to_le16 ( 0 ), - .size = 0, - .ifg = 0, -}; - -/****************************************************************************** - * - * Register access - * - ****************************************************************************** - */ - -/** - * Read register - * - * @v asix AXGE device - * @v offset Register offset - * @v data Data buffer - * @v len Length of data - * @ret rc Return status code - */ -static inline int axge_read_register ( struct axge_device *axge, - unsigned int offset, void *data, - size_t len ) { - - return usb_control ( axge->usb, AXGE_READ_MAC_REGISTER, - offset, len, data, len ); -} - -/** - * Read one-byte register - * - * @v asix AXGE device - * @v offset Register offset - * @v value Value to fill in - * @ret rc Return status code - */ -static inline int axge_read_byte ( struct axge_device *axge, - unsigned int offset, uint8_t *value ) { - - return axge_read_register ( axge, offset, value, sizeof ( *value ) ); -} - -/** - * Read two-byte register - * - * @v asix AXGE device - * @v offset Register offset - * @v value Value to fill in - * @ret rc Return status code - */ -static inline int axge_read_word ( struct axge_device *axge, - unsigned int offset, uint16_t *value ) { - - return axge_read_register ( axge, offset, value, sizeof ( *value ) ); -} - -/** - * Read four-byte register - * - * @v asix AXGE device - * @v offset Register offset - * @v value Value to fill in - * @ret rc Return status code - */ -static inline int axge_read_dword ( struct axge_device *axge, - unsigned int offset, uint32_t *value ) { - - return axge_read_register ( axge, offset, value, sizeof ( *value ) ); -} - -/** - * Write register - * - * @v asix AXGE device - * @v offset Register offset - * @v data Data buffer - * @v len Length of data - * @ret rc Return status code - */ -static inline int axge_write_register ( struct axge_device *axge, - unsigned int offset, void *data, - size_t len ) { - - return usb_control ( axge->usb, AXGE_WRITE_MAC_REGISTER, - offset, len, data, len ); -} - -/** - * Write one-byte register - * - * @v asix AXGE device - * @v offset Register offset - * @v value Value - * @ret rc Return status code - */ -static inline int axge_write_byte ( struct axge_device *axge, - unsigned int offset, uint8_t value ) { - - return axge_write_register ( axge, offset, &value, sizeof ( value )); -} - -/** - * Write two-byte register - * - * @v asix AXGE device - * @v offset Register offset - * @v value Value - * @ret rc Return status code - */ -static inline int axge_write_word ( struct axge_device *axge, - unsigned int offset, uint16_t value ) { - - return axge_write_register ( axge, offset, &value, sizeof ( value )); -} - -/** - * Write one-byte register - * - * @v asix AXGE device - * @v offset Register offset - * @v value Value - * @ret rc Return status code - */ -static inline int axge_write_dword ( struct axge_device *axge, - unsigned int offset, uint32_t value ) { - - return axge_write_register ( axge, offset, &value, sizeof ( value )); -} - -/****************************************************************************** - * - * Link status - * - ****************************************************************************** - */ - -/** - * Get link status - * - * @v asix AXGE device - * @ret rc Return status code - */ -static int axge_check_link ( struct axge_device *axge ) { - struct net_device *netdev = axge->netdev; - uint8_t plsr; - int rc; - - /* Read physical link status register */ - if ( ( rc = axge_read_byte ( axge, AXGE_PLSR, &plsr ) ) != 0 ) { - DBGC ( axge, "AXGE %p could not read PLSR: %s\n", - axge, strerror ( rc ) ); - return rc; - } - - /* Update link status */ - if ( plsr & AXGE_PLSR_EPHY_ANY ) { - DBGC ( axge, "AXGE %p link up (PLSR %02x)\n", axge, plsr ); - netdev_link_up ( netdev ); - } else { - DBGC ( axge, "AXGE %p link down (PLSR %02x)\n", axge, plsr ); - netdev_link_down ( netdev ); - } - - return 0; -} - -/****************************************************************************** - * - * AXGE communications interface - * - ****************************************************************************** - */ - -/** - * Complete interrupt transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void axge_intr_complete ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int rc ) { - struct axge_device *axge = container_of ( ep, struct axge_device, - usbnet.intr ); - struct net_device *netdev = axge->netdev; - struct axge_interrupt *intr; - size_t len = iob_len ( iobuf ); - unsigned int link_ok; - - /* Profile completions */ - profile_start ( &axge_intr_profiler ); - - /* Ignore packets cancelled when the endpoint closes */ - if ( ! ep->open ) - goto ignore; - - /* Drop packets with errors */ - if ( rc != 0 ) { - DBGC ( axge, "AXGE %p interrupt failed: %s\n", - axge, strerror ( rc ) ); - DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) ); - goto error; - } - - /* Extract message header */ - if ( len < sizeof ( *intr ) ) { - DBGC ( axge, "AXGE %p underlength interrupt:\n", axge ); - DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) ); - rc = -EINVAL; - goto error; - } - intr = iobuf->data; - - /* Check magic signature */ - if ( intr->magic != cpu_to_le16 ( AXGE_INTR_MAGIC ) ) { - DBGC ( axge, "AXGE %p malformed interrupt:\n", axge ); - DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) ); - rc = -EINVAL; - goto error; - } - - /* Extract link status */ - link_ok = ( intr->link & cpu_to_le16 ( AXGE_INTR_LINK_PPLS ) ); - if ( link_ok && ! netdev_link_ok ( netdev ) ) { - DBGC ( axge, "AXGE %p link up\n", axge ); - netdev_link_up ( netdev ); - } else if ( netdev_link_ok ( netdev ) && ! link_ok ) { - DBGC ( axge, "AXGE %p link down\n", axge ); - netdev_link_down ( netdev ); - } - - /* Free I/O buffer */ - free_iob ( iobuf ); - profile_stop ( &axge_intr_profiler ); - - return; - - error: - netdev_rx_err ( netdev, iob_disown ( iobuf ), rc ); - ignore: - free_iob ( iobuf ); - return; -} - -/** Interrupt endpoint operations */ -static struct usb_endpoint_driver_operations axge_intr_operations = { - .complete = axge_intr_complete, -}; - -/****************************************************************************** - * - * AXGE data interface - * - ****************************************************************************** - */ - -/** - * Complete bulk IN transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void axge_in_complete ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int rc ) { - struct axge_device *axge = container_of ( ep, struct axge_device, - usbnet.in ); - struct net_device *netdev = axge->netdev; - struct axge_rx_footer *ftr; - struct axge_rx_descriptor *desc; - struct io_buffer *pkt; - unsigned int count; - unsigned int offset; - size_t len; - size_t padded_len; - - /* Profile receive completions */ - profile_start ( &axge_in_profiler ); - - /* Ignore packets cancelled when the endpoint closes */ - if ( ! ep->open ) - goto ignore; - - /* Record USB errors against the network device */ - if ( rc != 0 ) { - DBGC ( axge, "AXGE %p bulk IN failed: %s\n", - axge, strerror ( rc ) ); - goto error; - } - - /* Sanity check */ - if ( iob_len ( iobuf ) < sizeof ( *ftr ) ) { - DBGC ( axge, "AXGE %p underlength bulk IN:\n", axge ); - DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) ); - rc = -EINVAL; - goto error; - } - - /* Parse ftr, strip ftr and descriptors */ - iob_unput ( iobuf, sizeof ( *ftr ) ); - ftr = ( iobuf->data + iob_len ( iobuf ) ); - count = le16_to_cpu ( ftr->count ); - if ( count == 0 ) { - DBGC ( axge, "AXGE %p zero-packet bulk IN:\n", axge ); - DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) ); - goto ignore; - } - offset = le16_to_cpu ( ftr->offset ); - if ( ( iob_len ( iobuf ) < offset ) || - ( ( iob_len ( iobuf ) - offset ) < ( count * sizeof ( *desc ) ) )){ - DBGC ( axge, "AXGE %p malformed bulk IN footer:\n", axge ); - DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) ); - rc = -EINVAL; - goto error; - } - desc = ( iobuf->data + offset ); - iob_unput ( iobuf, ( iob_len ( iobuf ) - offset ) ); - - /* Process packets */ - for ( ; count-- ; desc++ ) { - - /* Parse descriptor */ - len = ( le16_to_cpu ( desc->len_flags ) & AXGE_RX_LEN_MASK ); - padded_len = ( ( len + AXGE_RX_LEN_PAD_ALIGN - 1 ) & - ~( AXGE_RX_LEN_PAD_ALIGN - 1 ) ); - if ( iob_len ( iobuf ) < padded_len ) { - DBGC ( axge, "AXGE %p malformed bulk IN descriptor:\n", - axge ); - DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) ); - rc = -EINVAL; - goto error; - } - - /* Check for previous dropped packets */ - if ( desc->len_flags & cpu_to_le16 ( AXGE_RX_CRC_ERROR ) ) - netdev_rx_err ( netdev, NULL, -EIO ); - if ( desc->len_flags & cpu_to_le16 ( AXGE_RX_DROP_ERROR ) ) - netdev_rx_err ( netdev, NULL, -ENOBUFS ); - - /* Allocate new I/O buffer, if applicable */ - if ( count ) { - - /* More packets remain: allocate a new buffer */ - pkt = alloc_iob ( AXGE_IN_RESERVE + len ); - if ( ! pkt ) { - /* Record error and continue */ - netdev_rx_err ( netdev, NULL, -ENOMEM ); - iob_pull ( iobuf, padded_len ); - continue; - } - iob_reserve ( pkt, AXGE_IN_RESERVE ); - memcpy ( iob_put ( pkt, len ), iobuf->data, len ); - iob_pull ( iobuf, padded_len ); - - } else { - - /* This is the last (or only) packet: use this buffer */ - iob_unput ( iobuf, ( padded_len - len ) ); - pkt = iob_disown ( iobuf ); - } - - /* Hand off to network stack */ - netdev_rx ( netdev, iob_disown ( pkt ) ); - } - - assert ( iobuf == NULL ); - profile_stop ( &axge_in_profiler ); - return; - - error: - netdev_rx_err ( netdev, iob_disown ( iobuf ), rc ); - ignore: - free_iob ( iobuf ); -} - -/** Bulk IN endpoint operations */ -static struct usb_endpoint_driver_operations axge_in_operations = { - .complete = axge_in_complete, -}; - -/** - * Transmit packet - * - * @v asix AXGE device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int axge_out_transmit ( struct axge_device *axge, - struct io_buffer *iobuf ) { - struct axge_tx_header *hdr; - size_t len = iob_len ( iobuf ); - int rc; - - /* Profile transmissions */ - profile_start ( &axge_out_profiler ); - - /* Prepend header */ - if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *hdr ) ) ) != 0 ) - return rc; - hdr = iob_push ( iobuf, sizeof ( *hdr ) ); - hdr->len = cpu_to_le32 ( len ); - hdr->wtf = 0; - - /* Enqueue I/O buffer */ - if ( ( rc = usb_stream ( &axge->usbnet.out, iobuf, 0 ) ) != 0 ) - return rc; - - profile_stop ( &axge_out_profiler ); - return 0; -} - -/** - * Complete bulk OUT transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void axge_out_complete ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int rc ) { - struct axge_device *axge = container_of ( ep, struct axge_device, - usbnet.out ); - struct net_device *netdev = axge->netdev; - - /* Report TX completion */ - netdev_tx_complete_err ( netdev, iobuf, rc ); -} - -/** Bulk OUT endpoint operations */ -static struct usb_endpoint_driver_operations axge_out_operations = { - .complete = axge_out_complete, -}; - -/****************************************************************************** - * - * Network device interface - * - ****************************************************************************** - */ - -/** - * Open network device - * - * @v netdev Network device - * @ret rc Return status code - */ -static int axge_open ( struct net_device *netdev ) { - struct axge_device *axge = netdev->priv; - uint16_t rcr; - int rc; - - /* Open USB network device */ - if ( ( rc = usbnet_open ( &axge->usbnet ) ) != 0 ) { - DBGC ( axge, "AXGE %p could not open: %s\n", - axge, strerror ( rc ) ); - goto err_open; - } - - /* Set MAC address */ - if ( ( rc = axge_write_register ( axge, AXGE_NIDR, - netdev->ll_addr, ETH_ALEN ) ) !=0){ - DBGC ( axge, "AXGE %p could not set MAC address: %s\n", - axge, strerror ( rc ) ); - goto err_write_mac; - } - - /* Enable receiver */ - rcr = cpu_to_le16 ( AXGE_RCR_PRO | AXGE_RCR_AMALL | - AXGE_RCR_AB | AXGE_RCR_SO ); - if ( ( rc = axge_write_word ( axge, AXGE_RCR, rcr ) ) != 0 ) { - DBGC ( axge, "AXGE %p could not write RCR: %s\n", - axge, strerror ( rc ) ); - goto err_write_rcr; - } - - /* Update link status */ - axge_check_link ( axge ); - - return 0; - - axge_write_word ( axge, AXGE_RCR, 0 ); - err_write_rcr: - err_write_mac: - usbnet_close ( &axge->usbnet ); - err_open: - return rc; -} - -/** - * Close network device - * - * @v netdev Network device - */ -static void axge_close ( struct net_device *netdev ) { - struct axge_device *axge = netdev->priv; - - /* Disable receiver */ - axge_write_word ( axge, AXGE_RCR, 0 ); - - /* Close USB network device */ - usbnet_close ( &axge->usbnet ); -} - -/** - * Transmit packet - * - * @v netdev Network device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int axge_transmit ( struct net_device *netdev, - struct io_buffer *iobuf ) { - struct axge_device *axge = netdev->priv; - int rc; - - /* Transmit packet */ - if ( ( rc = axge_out_transmit ( axge, iobuf ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Poll for completed and received packets - * - * @v netdev Network device - */ -static void axge_poll ( struct net_device *netdev ) { - struct axge_device *axge = netdev->priv; - int rc; - - /* Poll USB bus */ - usb_poll ( axge->bus ); - - /* Refill endpoints */ - if ( ( rc = usbnet_refill ( &axge->usbnet ) ) != 0 ) - netdev_rx_err ( netdev, NULL, rc ); -} - -/** AXGE network device operations */ -static struct net_device_operations axge_operations = { - .open = axge_open, - .close = axge_close, - .transmit = axge_transmit, - .poll = axge_poll, -}; - -/****************************************************************************** - * - * USB interface - * - ****************************************************************************** - */ - -/** - * Probe device - * - * @v func USB function - * @v config Configuration descriptor - * @ret rc Return status code - */ -static int axge_probe ( struct usb_function *func, - struct usb_configuration_descriptor *config ) { - struct usb_device *usb = func->usb; - struct net_device *netdev; - struct axge_device *axge; - uint16_t epprcr; - uint16_t msr; - uint8_t csr; - int rc; - - /* Allocate and initialise structure */ - netdev = alloc_etherdev ( sizeof ( *axge ) ); - if ( ! netdev ) { - rc = -ENOMEM; - goto err_alloc; - } - netdev_init ( netdev, &axge_operations ); - netdev->dev = &func->dev; - axge = netdev->priv; - memset ( axge, 0, sizeof ( *axge ) ); - axge->usb = usb; - axge->bus = usb->port->hub->bus; - axge->netdev = netdev; - usbnet_init ( &axge->usbnet, func, &axge_intr_operations, - &axge_in_operations, &axge_out_operations ); - usb_refill_init ( &axge->usbnet.intr, 0, 0, AXGE_INTR_MAX_FILL ); - usb_refill_init ( &axge->usbnet.in, AXGE_IN_RESERVE, - AXGE_IN_MTU, AXGE_IN_MAX_FILL ); - DBGC ( axge, "AXGE %p on %s\n", axge, func->name ); - - /* Describe USB network device */ - if ( ( rc = usbnet_describe ( &axge->usbnet, config ) ) != 0 ) { - DBGC ( axge, "AXGE %p could not describe: %s\n", - axge, strerror ( rc ) ); - goto err_describe; - } - - /* Fetch MAC address */ - if ( ( rc = axge_read_register ( axge, AXGE_NIDR, netdev->hw_addr, - ETH_ALEN ) ) != 0 ) { - DBGC ( axge, "AXGE %p could not fetch MAC address: %s\n", - axge, strerror ( rc ) ); - goto err_read_mac; - } - - /* Power up PHY */ - if ( ( rc = axge_write_word ( axge, AXGE_EPPRCR, 0 ) ) != 0 ) { - DBGC ( axge, "AXGE %p could not write EPPRCR: %s\n", - axge, strerror ( rc ) ); - goto err_write_epprcr_off; - } - epprcr = cpu_to_le16 ( AXGE_EPPRCR_IPRL ); - if ( ( rc = axge_write_word ( axge, AXGE_EPPRCR, epprcr ) ) != 0){ - DBGC ( axge, "AXGE %p could not write EPPRCR: %s\n", - axge, strerror ( rc ) ); - goto err_write_epprcr_on; - } - mdelay ( AXGE_EPPRCR_DELAY_MS ); - - /* Select clocks */ - csr = ( AXGE_CSR_BCS | AXGE_CSR_ACS ); - if ( ( rc = axge_write_byte ( axge, AXGE_CSR, csr ) ) != 0){ - DBGC ( axge, "AXGE %p could not write CSR: %s\n", - axge, strerror ( rc ) ); - goto err_write_csr; - } - mdelay ( AXGE_CSR_DELAY_MS ); - - /* Configure bulk IN pipeline */ - if ( ( rc = axge_write_register ( axge, AXGE_BICR, &axge_bicr, - sizeof ( axge_bicr ) ) ) != 0 ){ - DBGC ( axge, "AXGE %p could not write BICR: %s\n", - axge, strerror ( rc ) ); - goto err_write_bicr; - } - - /* Set medium status */ - msr = cpu_to_le16 ( AXGE_MSR_GM | AXGE_MSR_FD | AXGE_MSR_RFC | - AXGE_MSR_TFC | AXGE_MSR_RE ); - if ( ( rc = axge_write_word ( axge, AXGE_MSR, msr ) ) != 0 ) { - DBGC ( axge, "AXGE %p could not write MSR: %s\n", - axge, strerror ( rc ) ); - goto err_write_msr; - } - - /* Register network device */ - if ( ( rc = register_netdev ( netdev ) ) != 0 ) - goto err_register; - - /* Update link status */ - axge_check_link ( axge ); - - usb_func_set_drvdata ( func, axge ); - return 0; - - unregister_netdev ( netdev ); - err_register: - err_write_msr: - err_write_bicr: - err_write_csr: - err_write_epprcr_on: - err_write_epprcr_off: - err_read_mac: - err_describe: - netdev_nullify ( netdev ); - netdev_put ( netdev ); - err_alloc: - return rc; -} - -/** - * Remove device - * - * @v func USB function - */ -static void axge_remove ( struct usb_function *func ) { - struct axge_device *axge = usb_func_get_drvdata ( func ); - struct net_device *netdev = axge->netdev; - - unregister_netdev ( netdev ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} - -/** AXGE device IDs */ -static struct usb_device_id axge_ids[] = { - { - .name = "ax88179", - .vendor = 0x0b95, - .product = 0x1790, - }, - { - .name = "ax88178a", - .vendor = 0x0b95, - .product = 0x178a, - }, - { - .name = "dub1312", - .vendor = 0x2001, - .product = 0x4a00, - }, - { - .name = "axge-sitecom", - .vendor = 0x0df6, - .product = 0x0072, - }, - { - .name = "axge-samsung", - .vendor = 0x04e8, - .product = 0xa100, - }, - { - .name = "onelinkdock", - .vendor = 0x17ef, - .product = 0x304b, - }, -}; - -/** AXGE driver */ -struct usb_driver axge_driver __usb_driver = { - .ids = axge_ids, - .id_count = ( sizeof ( axge_ids ) / sizeof ( axge_ids[0] ) ), - .class = USB_CLASS_ID ( USB_ANY_ID, USB_ANY_ID, USB_ANY_ID ), - .score = USB_SCORE_NORMAL, - .probe = axge_probe, - .remove = axge_remove, -}; diff --git a/roms/ipxe/src/drivers/net/axge.h b/roms/ipxe/src/drivers/net/axge.h deleted file mode 100644 index 65bf911c5..000000000 --- a/roms/ipxe/src/drivers/net/axge.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef _AXGE_H -#define _AXGE_H - -/** @file - * - * Asix 10/100/1000 USB Ethernet driver - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/usb.h> -#include <ipxe/usbnet.h> - -/** Read MAC register */ -#define AXGE_READ_MAC_REGISTER \ - ( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \ - USB_REQUEST_TYPE ( 0x01 ) ) - -/** Write MAC register */ -#define AXGE_WRITE_MAC_REGISTER \ - ( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \ - USB_REQUEST_TYPE ( 0x01 ) ) - -/** Physical Link Status Register */ -#define AXGE_PLSR 0x02 -#define AXGE_PLSR_EPHY_10 0x10 /**< Ethernet at 10Mbps */ -#define AXGE_PLSR_EPHY_100 0x20 /**< Ethernet at 100Mbps */ -#define AXGE_PLSR_EPHY_1000 0x40 /**< Ethernet at 1000Mbps */ -#define AXGE_PLSR_EPHY_ANY \ - ( AXGE_PLSR_EPHY_10 | \ - AXGE_PLSR_EPHY_100 | \ - AXGE_PLSR_EPHY_1000 ) - -/** RX Control Register */ -#define AXGE_RCR 0x0b -#define AXGE_RCR_PRO 0x0001 /**< Promiscuous mode */ -#define AXGE_RCR_AMALL 0x0002 /**< Accept all multicasts */ -#define AXGE_RCR_AB 0x0008 /**< Accept broadcasts */ -#define AXGE_RCR_SO 0x0080 /**< Start operation */ - -/** Node ID Register */ -#define AXGE_NIDR 0x10 - -/** Medium Status Register */ -#define AXGE_MSR 0x22 -#define AXGE_MSR_GM 0x0001 /**< Gigabit mode */ -#define AXGE_MSR_FD 0x0002 /**< Full duplex */ -#define AXGE_MSR_RFC 0x0010 /**< RX flow control enable */ -#define AXGE_MSR_TFC 0x0020 /**< TX flow control enable */ -#define AXGE_MSR_RE 0x0100 /**< Receive enable */ - -/** Ethernet PHY Power and Reset Control Register */ -#define AXGE_EPPRCR 0x26 -#define AXGE_EPPRCR_IPRL 0x0020 /**< Undocumented */ - -/** Delay after initialising EPPRCR */ -#define AXGE_EPPRCR_DELAY_MS 200 - -/** Bulk IN Control Register (undocumented) */ -#define AXGE_BICR 0x2e - -/** Bulk IN Control (undocumented) */ -struct axge_bulk_in_control { - /** Control */ - uint8_t ctrl; - /** Timer */ - uint16_t timer; - /** Size */ - uint8_t size; - /** Inter-frame gap */ - uint8_t ifg; -} __attribute__ (( packed )); - -/** Clock Select Register (undocumented) */ -#define AXGE_CSR 0x33 -#define AXGE_CSR_BCS 0x01 /**< Undocumented */ -#define AXGE_CSR_ACS 0x02 /**< Undocumented */ - -/** Delay after initialising CSR */ -#define AXGE_CSR_DELAY_MS 100 - -/** Transmit packet header */ -struct axge_tx_header { - /** Packet length */ - uint32_t len; - /** Answers on a postcard, please */ - uint32_t wtf; -} __attribute__ (( packed )); - -/** Receive packet footer */ -struct axge_rx_footer { - /** Packet count */ - uint16_t count; - /** Header offset */ - uint16_t offset; -} __attribute__ (( packed )); - -/** Receive packet descriptor */ -struct axge_rx_descriptor { - /** Checksum information */ - uint16_t check; - /** Length and error flags */ - uint16_t len_flags; -} __attribute__ (( packed )); - -/** Receive packet length mask */ -#define AXGE_RX_LEN_MASK 0x1fff - -/** Receive packet length alignment */ -#define AXGE_RX_LEN_PAD_ALIGN 8 - -/** Receive packet CRC error */ -#define AXGE_RX_CRC_ERROR 0x2000 - -/** Receive packet dropped error */ -#define AXGE_RX_DROP_ERROR 0x8000 - -/** Interrupt data */ -struct axge_interrupt { - /** Magic signature */ - uint16_t magic; - /** Link state */ - uint16_t link; - /** PHY register MR01 */ - uint16_t mr01; - /** PHY register MR05 */ - uint16_t mr05; -} __attribute__ (( packed )); - -/** Interrupt magic signature */ -#define AXGE_INTR_MAGIC 0x00a1 - -/** Link is up */ -#define AXGE_INTR_LINK_PPLS 0x0001 - -/** An AXGE network device */ -struct axge_device { - /** USB device */ - struct usb_device *usb; - /** USB bus */ - struct usb_bus *bus; - /** Network device */ - struct net_device *netdev; - /** USB network device */ - struct usbnet_device usbnet; -}; - -/** Interrupt maximum fill level - * - * This is a policy decision. - */ -#define AXGE_INTR_MAX_FILL 2 - -/** Bulk IN maximum fill level - * - * This is a policy decision. - */ -#define AXGE_IN_MAX_FILL 8 - -/** Bulk IN buffer size - * - * This is a policy decision. - */ -#define AXGE_IN_MTU 2048 - -/** Amount of space to reserve at start of bulk IN buffers - * - * This is required to allow for protocols such as ARP which may reuse - * a received I/O buffer for transmission. - */ -#define AXGE_IN_RESERVE sizeof ( struct axge_tx_header ) - -#endif /* _AXGE_H */ diff --git a/roms/ipxe/src/drivers/net/dm96xx.c b/roms/ipxe/src/drivers/net/dm96xx.c index 61b957be9..58d8dd964 100644 --- a/roms/ipxe/src/drivers/net/dm96xx.c +++ b/roms/ipxe/src/drivers/net/dm96xx.c @@ -532,8 +532,8 @@ static int dm96xx_probe ( struct usb_function *func, dm96xx->netdev = netdev; usbnet_init ( &dm96xx->usbnet, func, &dm96xx_intr_operations, &dm96xx_in_operations, &dm96xx_out_operations ); - usb_refill_init ( &dm96xx->usbnet.intr, 0, 0, DM96XX_INTR_MAX_FILL ); - usb_refill_init ( &dm96xx->usbnet.in, 0, DM96XX_IN_MTU, + usb_refill_init ( &dm96xx->usbnet.intr, 0, DM96XX_INTR_MAX_FILL ); + usb_refill_init ( &dm96xx->usbnet.in, DM96XX_IN_MTU, DM96XX_IN_MAX_FILL ); DBGC ( dm96xx, "DM96XX %p on %s\n", dm96xx, func->name ); @@ -666,8 +666,6 @@ static struct usb_device_id dm96xx_ids[] = { struct usb_driver dm96xx_driver __usb_driver = { .ids = dm96xx_ids, .id_count = ( sizeof ( dm96xx_ids ) / sizeof ( dm96xx_ids[0] ) ), - .class = USB_CLASS_ID ( USB_ANY_ID, USB_ANY_ID, USB_ANY_ID ), - .score = USB_SCORE_NORMAL, .probe = dm96xx_probe, .remove = dm96xx_remove, }; diff --git a/roms/ipxe/src/drivers/net/ecm.c b/roms/ipxe/src/drivers/net/ecm.c index f2d9161c1..8c84ea9e9 100644 --- a/roms/ipxe/src/drivers/net/ecm.c +++ b/roms/ipxe/src/drivers/net/ecm.c @@ -437,8 +437,8 @@ static int ecm_probe ( struct usb_function *func, ecm->netdev = netdev; usbnet_init ( &ecm->usbnet, func, &ecm_intr_operations, &ecm_in_operations, &ecm_out_operations ); - usb_refill_init ( &ecm->usbnet.intr, 0, 0, ECM_INTR_MAX_FILL ); - usb_refill_init ( &ecm->usbnet.in, 0, ECM_IN_MTU, ECM_IN_MAX_FILL ); + usb_refill_init ( &ecm->usbnet.intr, 0, ECM_INTR_MAX_FILL ); + usb_refill_init ( &ecm->usbnet.in, ECM_IN_MTU, ECM_IN_MAX_FILL ); DBGC ( ecm, "ECM %p on %s\n", ecm, func->name ); /* Describe USB network device */ @@ -503,6 +503,11 @@ static struct usb_device_id ecm_ids[] = { .name = "cdc-ecm", .vendor = USB_ANY_ID, .product = USB_ANY_ID, + .class = { + .class = USB_CLASS_CDC, + .subclass = USB_SUBCLASS_CDC_ECM, + .protocol = 0, + }, }, }; @@ -510,8 +515,6 @@ static struct usb_device_id ecm_ids[] = { struct usb_driver ecm_driver __usb_driver = { .ids = ecm_ids, .id_count = ( sizeof ( ecm_ids ) / sizeof ( ecm_ids[0] ) ), - .class = USB_CLASS_ID ( USB_CLASS_CDC, USB_SUBCLASS_CDC_ECM, 0 ), - .score = USB_SCORE_NORMAL, .probe = ecm_probe, .remove = ecm_remove, }; diff --git a/roms/ipxe/src/drivers/net/efi/nii.c b/roms/ipxe/src/drivers/net/efi/nii.c index d68b36cc3..b91848f5c 100644 --- a/roms/ipxe/src/drivers/net/efi/nii.c +++ b/roms/ipxe/src/drivers/net/efi/nii.c @@ -1125,8 +1125,8 @@ int nii_start ( struct efi_device *efidev ) { /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) goto err_register_netdev; - DBGC ( nii, "NII %s registered as %s for %s\n", nii->dev.name, - netdev->name, efi_handle_name ( device ) ); + DBGC ( nii, "NII %s registered as %s for %p %s\n", nii->dev.name, + netdev->name, device, efi_handle_name ( device ) ); /* Set initial link state (if media detection is not supported) */ if ( ! nii->media ) diff --git a/roms/ipxe/src/drivers/net/efi/snp.c b/roms/ipxe/src/drivers/net/efi/snp.c index fbd606902..acfcfba9f 100644 --- a/roms/ipxe/src/drivers/net/efi/snp.c +++ b/roms/ipxe/src/drivers/net/efi/snp.c @@ -48,8 +48,8 @@ static int snp_supported ( EFI_HANDLE device ) { /* Check that this is not a device we are providing ourselves */ if ( find_snpdev ( device ) != NULL ) { - DBGCP ( device, "SNP %s is provided by this binary\n", - efi_handle_name ( device ) ); + DBGCP ( device, "SNP %p %s is provided by this binary\n", + device, efi_handle_name ( device ) ); return -ENOTTY; } @@ -58,12 +58,12 @@ static int snp_supported ( EFI_HANDLE device ) { &efi_simple_network_protocol_guid, NULL, efi_image_handle, device, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){ - DBGCP ( device, "SNP %s is not an SNP device\n", - efi_handle_name ( device ) ); + DBGCP ( device, "SNP %p %s is not an SNP device\n", + device, efi_handle_name ( device ) ); return -EEFI ( efirc ); } - DBGC ( device, "SNP %s is an SNP device\n", - efi_handle_name ( device ) ); + DBGC ( device, "SNP %p %s is an SNP device\n", + device, efi_handle_name ( device ) ); return 0; } @@ -80,8 +80,8 @@ static int nii_supported ( EFI_HANDLE device ) { /* Check that this is not a device we are providing ourselves */ if ( find_snpdev ( device ) != NULL ) { - DBGCP ( device, "NII %s is provided by this binary\n", - efi_handle_name ( device ) ); + DBGCP ( device, "NII %p %s is provided by this binary\n", + device, efi_handle_name ( device ) ); return -ENOTTY; } @@ -90,12 +90,12 @@ static int nii_supported ( EFI_HANDLE device ) { &efi_nii31_protocol_guid, NULL, efi_image_handle, device, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){ - DBGCP ( device, "NII %s is not an NII device\n", - efi_handle_name ( device ) ); + DBGCP ( device, "NII %p %s is not an NII device\n", + device, efi_handle_name ( device ) ); return -EEFI ( efirc ); } - DBGC ( device, "NII %s is an NII device\n", - efi_handle_name ( device ) ); + DBGC ( device, "NII %p %s is an NII device\n", + device, efi_handle_name ( device ) ); return 0; } diff --git a/roms/ipxe/src/drivers/net/efi/snpnet.c b/roms/ipxe/src/drivers/net/efi/snpnet.c index 88474b0be..96642c4ca 100644 --- a/roms/ipxe/src/drivers/net/efi/snpnet.c +++ b/roms/ipxe/src/drivers/net/efi/snpnet.c @@ -191,7 +191,6 @@ static void snpnet_poll_tx ( struct net_device *netdev ) { int rc; /* Get status */ - txbuf = NULL; if ( ( efirc = snp->snp->GetStatus ( snp->snp, &irq, &txbuf ) ) != 0 ) { rc = -EEFI ( efirc ); DBGC ( snp, "SNP %s could not get status: %s\n", @@ -432,8 +431,8 @@ int snpnet_start ( struct efi_device *efidev ) { ( EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){ rc = -EEFI ( efirc ); - DBGC ( device, "SNP %s cannot open SNP protocol: %s\n", - efi_handle_name ( device ), strerror ( rc ) ); + DBGC ( device, "SNP %p %s cannot open SNP protocol: %s\n", + device, efi_handle_name ( device ), strerror ( rc ) ); DBGC_EFI_OPENERS ( device, device, &efi_simple_network_protocol_guid ); goto err_open_protocol; @@ -464,30 +463,32 @@ int snpnet_start ( struct efi_device *efidev ) { if ( ( mode->State == EfiSimpleNetworkStopped ) && ( ( efirc = snp->snp->Start ( snp->snp ) ) != 0 ) ) { rc = -EEFI ( efirc ); - DBGC ( device, "SNP %s could not start: %s\n", + DBGC ( device, "SNP %p %s could not start: %s\n", device, efi_handle_name ( device ), strerror ( rc ) ); goto err_start; } if ( ( mode->State == EfiSimpleNetworkInitialized ) && ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) ) { rc = -EEFI ( efirc ); - DBGC ( device, "SNP %s could not shut down: %s\n", + DBGC ( device, "SNP %p %s could not shut down: %s\n", device, efi_handle_name ( device ), strerror ( rc ) ); goto err_shutdown; } /* Populate network device parameters */ if ( mode->HwAddressSize != netdev->ll_protocol->hw_addr_len ) { - DBGC ( device, "SNP %s has invalid hardware address length " - "%d\n", efi_handle_name ( device ), mode->HwAddressSize); + DBGC ( device, "SNP %p %s has invalid hardware address " + "length %d\n", device, efi_handle_name ( device ), + mode->HwAddressSize ); rc = -ENOTSUP; goto err_hw_addr_len; } memcpy ( netdev->hw_addr, &mode->PermanentAddress, netdev->ll_protocol->hw_addr_len ); if ( mode->HwAddressSize != netdev->ll_protocol->ll_addr_len ) { - DBGC ( device, "SNP %s has invalid link-layer address length " - "%d\n", efi_handle_name ( device ), mode->HwAddressSize); + DBGC ( device, "SNP %p %s has invalid link-layer address " + "length %d\n", device, efi_handle_name ( device ), + mode->HwAddressSize ); rc = -ENOTSUP; goto err_ll_addr_len; } @@ -499,8 +500,8 @@ int snpnet_start ( struct efi_device *efidev ) { /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) goto err_register_netdev; - DBGC ( device, "SNP %s registered as %s\n", - efi_handle_name ( device ), netdev->name ); + DBGC ( device, "SNP %p %s registered as %s\n", + device, efi_handle_name ( device ), netdev->name ); /* Set initial link state */ if ( snp->snp->Mode->MediaPresentSupported ) { @@ -546,7 +547,7 @@ void snpnet_stop ( struct efi_device *efidev ) { /* Stop SNP protocol */ if ( ( efirc = snp->snp->Stop ( snp->snp ) ) != 0 ) { rc = -EEFI ( efirc ); - DBGC ( device, "SNP %s could not stop: %s\n", + DBGC ( device, "SNP %p %s could not stop: %s\n", device, efi_handle_name ( device ), strerror ( rc ) ); /* Nothing we can do about this */ } diff --git a/roms/ipxe/src/drivers/net/efi/snponly.c b/roms/ipxe/src/drivers/net/efi/snponly.c index cb7ea1bbc..73abfdbf4 100644 --- a/roms/ipxe/src/drivers/net/efi/snponly.c +++ b/roms/ipxe/src/drivers/net/efi/snponly.c @@ -81,14 +81,14 @@ static int chained_locate ( struct chained_protocol *chained ) { /* Locate handle supporting this protocol */ if ( ( rc = efi_locate_device ( device, chained->protocol, &parent ) ) != 0 ) { - DBGC ( device, "CHAINED %s does not support %s: %s\n", - efi_handle_name ( device ), + DBGC ( device, "CHAINED %p %s does not support %s: %s\n", + device, efi_handle_name ( device ), efi_guid_ntoa ( chained->protocol ), strerror ( rc ) ); goto err_locate_device; } - DBGC ( device, "CHAINED %s found %s on ", efi_handle_name ( device ), - efi_guid_ntoa ( chained->protocol ) ); - DBGC ( device, "%s\n", efi_handle_name ( parent ) ); + DBGC ( device, "CHAINED %p %s found %s on ", device, + efi_handle_name ( device ), efi_guid_ntoa ( chained->protocol )); + DBGC ( device, "%p %s\n", parent, efi_handle_name ( parent ) ); /* Get protocol instance */ if ( ( efirc = bs->OpenProtocol ( parent, chained->protocol, @@ -96,11 +96,11 @@ static int chained_locate ( struct chained_protocol *chained ) { device, EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ rc = -EEFI ( efirc ); - DBGC ( device, "CHAINED %s could not open %s on ", - efi_handle_name ( device ), + DBGC ( device, "CHAINED %p %s could not open %s on ", + device, efi_handle_name ( device ), efi_guid_ntoa ( chained->protocol ) ); - DBGC ( device, "%s: %s\n", - efi_handle_name ( parent ), strerror ( rc ) ); + DBGC ( device, "%p %s: %s\n", + parent, efi_handle_name ( parent ), strerror ( rc ) ); goto err_open_protocol; } @@ -130,25 +130,25 @@ static int chained_supported ( EFI_HANDLE device, efi_image_handle, device, EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ rc = -EEFI ( efirc ); - DBGCP ( device, "CHAINED %s is not a %s device\n", - efi_handle_name ( device ), + DBGCP ( device, "CHAINED %p %s is not a %s device\n", + device, efi_handle_name ( device ), efi_guid_ntoa ( chained->protocol ) ); goto err_open_protocol; } /* Test for a match against the chainloading device */ if ( interface != chained->interface ) { - DBGC ( device, "CHAINED %s %p is not the chainloaded %s\n", - efi_handle_name ( device ), interface, - efi_guid_ntoa ( chained->protocol ) ); + DBGC ( device, "CHAINED %p %s %p is not the chainloaded " + "%s\n", device, efi_handle_name ( device ), + interface, efi_guid_ntoa ( chained->protocol ) ); rc = -ENOTTY; goto err_no_match; } /* Success */ rc = 0; - DBGC ( device, "CHAINED %s %p is the chainloaded %s\n", - efi_handle_name ( device ), interface, + DBGC ( device, "CHAINED %p %s %p is the chainloaded %s\n", + device, efi_handle_name ( device ), interface, efi_guid_ntoa ( chained->protocol ) ); err_no_match: diff --git a/roms/ipxe/src/drivers/net/eoib.c b/roms/ipxe/src/drivers/net/eoib.c deleted file mode 100644 index f58e74b7d..000000000 --- a/roms/ipxe/src/drivers/net/eoib.c +++ /dev/null @@ -1,895 +0,0 @@ -/* - * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <ipxe/errortab.h> -#include <ipxe/malloc.h> -#include <ipxe/iobuf.h> -#include <ipxe/if_ether.h> -#include <ipxe/netdevice.h> -#include <ipxe/ethernet.h> -#include <ipxe/infiniband.h> -#include <ipxe/ib_mcast.h> -#include <ipxe/ib_pathrec.h> -#include <ipxe/eoib.h> - -/** @file - * - * Ethernet over Infiniband - * - */ - -/** Number of EoIB send work queue entries */ -#define EOIB_NUM_SEND_WQES 8 - -/** Number of EoIB receive work queue entries */ -#define EOIB_NUM_RECV_WQES 4 - -/** Number of EoIB completion queue entries */ -#define EOIB_NUM_CQES 16 - -/** Link status for "broadcast join in progress" */ -#define EINPROGRESS_JOINING __einfo_error ( EINFO_EINPROGRESS_JOINING ) -#define EINFO_EINPROGRESS_JOINING __einfo_uniqify \ - ( EINFO_EINPROGRESS, 0x01, "Joining" ) - -/** Human-readable message for the link status */ -struct errortab eoib_errors[] __errortab = { - __einfo_errortab ( EINFO_EINPROGRESS_JOINING ), -}; - -/** List of EoIB devices */ -static LIST_HEAD ( eoib_devices ); - -static struct net_device_operations eoib_operations; - -/**************************************************************************** - * - * EoIB peer cache - * - **************************************************************************** - */ - -/** An EoIB peer cache entry */ -struct eoib_peer { - /** List of EoIB peer cache entries */ - struct list_head list; - /** Ethernet MAC */ - uint8_t mac[ETH_ALEN]; - /** Infiniband address vector */ - struct ib_address_vector av; -}; - -/** - * Find EoIB peer cache entry - * - * @v eoib EoIB device - * @v mac Ethernet MAC - * @ret peer EoIB peer, or NULL if not found - */ -static struct eoib_peer * eoib_find_peer ( struct eoib_device *eoib, - const uint8_t *mac ) { - struct eoib_peer *peer; - - /* Find peer cache entry */ - list_for_each_entry ( peer, &eoib->peers, list ) { - if ( memcmp ( mac, peer->mac, sizeof ( peer->mac ) ) == 0 ) { - /* Move peer to start of list */ - list_del ( &peer->list ); - list_add ( &peer->list, &eoib->peers ); - return peer; - } - } - - return NULL; -} - -/** - * Create EoIB peer cache entry - * - * @v eoib EoIB device - * @v mac Ethernet MAC - * @ret peer EoIB peer, or NULL on error - */ -static struct eoib_peer * eoib_create_peer ( struct eoib_device *eoib, - const uint8_t *mac ) { - struct eoib_peer *peer; - - /* Allocate and initialise peer cache entry */ - peer = zalloc ( sizeof ( *peer ) ); - if ( peer ) { - memcpy ( peer->mac, mac, sizeof ( peer->mac ) ); - list_add ( &peer->list, &eoib->peers ); - } - return peer; -} - -/** - * Flush EoIB peer cache - * - * @v eoib EoIB device - */ -static void eoib_flush_peers ( struct eoib_device *eoib ) { - struct eoib_peer *peer; - struct eoib_peer *tmp; - - list_for_each_entry_safe ( peer, tmp, &eoib->peers, list ) { - list_del ( &peer->list ); - free ( peer ); - } -} - -/** - * Discard some entries from the peer cache - * - * @ret discarded Number of cached items discarded - */ -static unsigned int eoib_discard ( void ) { - struct net_device *netdev; - struct eoib_device *eoib; - struct eoib_peer *peer; - unsigned int discarded = 0; - - /* Try to discard one cache entry for each EoIB device */ - for_each_netdev ( netdev ) { - - /* Skip non-EoIB devices */ - if ( netdev->op != &eoib_operations ) - continue; - eoib = netdev->priv; - - /* Discard least recently used cache entry (if any) */ - list_for_each_entry_reverse ( peer, &eoib->peers, list ) { - list_del ( &peer->list ); - free ( peer ); - discarded++; - break; - } - } - - return discarded; -} - -/** EoIB cache discarder */ -struct cache_discarder eoib_discarder __cache_discarder ( CACHE_EXPENSIVE ) = { - .discard = eoib_discard, -}; - -/** - * Find destination address vector - * - * @v eoib EoIB device - * @v mac Ethernet MAC - * @ret av Address vector, or NULL to send as broadcast - */ -static struct ib_address_vector * eoib_tx_av ( struct eoib_device *eoib, - const uint8_t *mac ) { - struct ib_device *ibdev = eoib->ibdev; - struct eoib_peer *peer; - int rc; - - /* If this is a broadcast or multicast MAC address, then send - * this packet as a broadcast. - */ - if ( is_multicast_ether_addr ( mac ) ) { - DBGCP ( eoib, "EoIB %s %s TX multicast\n", - eoib->name, eth_ntoa ( mac ) ); - return NULL; - } - - /* If we have no peer cache entry, then create one and send - * this packet as a broadcast. - */ - peer = eoib_find_peer ( eoib, mac ); - if ( ! peer ) { - DBGC ( eoib, "EoIB %s %s TX unknown\n", - eoib->name, eth_ntoa ( mac ) ); - eoib_create_peer ( eoib, mac ); - return NULL; - } - - /* If we have not yet recorded a received GID and QPN for this - * peer cache entry, then send this packet as a broadcast. - */ - if ( ! peer->av.gid_present ) { - DBGCP ( eoib, "EoIB %s %s TX not yet recorded\n", - eoib->name, eth_ntoa ( mac ) ); - return NULL; - } - - /* If we have not yet resolved a path to this peer, then send - * this packet as a broadcast. - */ - if ( ( rc = ib_resolve_path ( ibdev, &peer->av ) ) != 0 ) { - DBGCP ( eoib, "EoIB %s %s TX not yet resolved\n", - eoib->name, eth_ntoa ( mac ) ); - return NULL; - } - - /* Force use of GRH even for local destinations */ - peer->av.gid_present = 1; - - /* We have a fully resolved peer: send this packet as a - * unicast. - */ - DBGCP ( eoib, "EoIB %s %s TX " IB_GID_FMT " QPN %#lx\n", eoib->name, - eth_ntoa ( mac ), IB_GID_ARGS ( &peer->av.gid ), peer->av.qpn ); - return &peer->av; -} - -/** - * Record source address vector - * - * @v eoib EoIB device - * @v mac Ethernet MAC - * @v lid Infiniband LID - */ -static void eoib_rx_av ( struct eoib_device *eoib, const uint8_t *mac, - const struct ib_address_vector *av ) { - const union ib_gid *gid = &av->gid; - unsigned long qpn = av->qpn; - struct eoib_peer *peer; - - /* Sanity checks */ - if ( ! av->gid_present ) { - DBGC ( eoib, "EoIB %s %s RX with no GID\n", - eoib->name, eth_ntoa ( mac ) ); - return; - } - - /* Find peer cache entry (if any) */ - peer = eoib_find_peer ( eoib, mac ); - if ( ! peer ) { - DBGCP ( eoib, "EoIB %s %s RX " IB_GID_FMT " (ignored)\n", - eoib->name, eth_ntoa ( mac ), IB_GID_ARGS ( gid ) ); - return; - } - - /* Some dubious EoIB implementations utilise an Ethernet-to- - * EoIB gateway that will send packets from the wrong QPN. - */ - if ( eoib_has_gateway ( eoib ) && - ( memcmp ( gid, &eoib->gateway.gid, sizeof ( *gid ) ) == 0 ) ) { - qpn = eoib->gateway.qpn; - } - - /* Do nothing if peer cache entry is complete and correct */ - if ( ( peer->av.lid == av->lid ) && ( peer->av.qpn == qpn ) ) { - DBGCP ( eoib, "EoIB %s %s RX unchanged\n", - eoib->name, eth_ntoa ( mac ) ); - return; - } - - /* Update peer cache entry */ - peer->av.qpn = qpn; - peer->av.qkey = eoib->broadcast.qkey; - peer->av.gid_present = 1; - memcpy ( &peer->av.gid, gid, sizeof ( peer->av.gid ) ); - DBGC ( eoib, "EoIB %s %s RX " IB_GID_FMT " QPN %#lx\n", eoib->name, - eth_ntoa ( mac ), IB_GID_ARGS ( &peer->av.gid ), peer->av.qpn ); -} - -/**************************************************************************** - * - * EoIB network device - * - **************************************************************************** - */ - -/** - * Transmit packet via EoIB network device - * - * @v netdev Network device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int eoib_transmit ( struct net_device *netdev, - struct io_buffer *iobuf ) { - struct eoib_device *eoib = netdev->priv; - struct eoib_header *eoib_hdr; - struct ethhdr *ethhdr; - struct ib_address_vector *av; - size_t zlen; - - /* Sanity checks */ - assert ( iob_len ( iobuf ) >= sizeof ( *ethhdr ) ); - assert ( iob_headroom ( iobuf ) >= sizeof ( *eoib_hdr ) ); - - /* Look up destination address vector */ - ethhdr = iobuf->data; - av = eoib_tx_av ( eoib, ethhdr->h_dest ); - - /* Prepend EoIB header */ - eoib_hdr = iob_push ( iobuf, sizeof ( *eoib_hdr ) ); - eoib_hdr->magic = htons ( EOIB_MAGIC ); - eoib_hdr->reserved = 0; - - /* Pad buffer to minimum Ethernet frame size */ - zlen = ( sizeof ( *eoib_hdr ) + ETH_ZLEN ); - assert ( zlen <= IOB_ZLEN ); - if ( iob_len ( iobuf ) < zlen ) - iob_pad ( iobuf, zlen ); - - /* If we have no unicast address then send as a broadcast, - * with a duplicate sent to the gateway if applicable. - */ - if ( ! av ) { - av = &eoib->broadcast; - if ( eoib_has_gateway ( eoib ) ) - eoib->duplicate ( eoib, iobuf ); - } - - /* Post send work queue entry */ - return ib_post_send ( eoib->ibdev, eoib->qp, av, iobuf ); -} - -/** - * Handle EoIB send completion - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void eoib_complete_send ( struct ib_device *ibdev __unused, - struct ib_queue_pair *qp, - struct io_buffer *iobuf, int rc ) { - struct eoib_device *eoib = ib_qp_get_ownerdata ( qp ); - - netdev_tx_complete_err ( eoib->netdev, iobuf, rc ); -} - -/** - * Handle EoIB receive completion - * - * @v ibdev Infiniband device - * @v qp Queue pair - * @v dest Destination address vector, or NULL - * @v source Source address vector, or NULL - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void eoib_complete_recv ( struct ib_device *ibdev __unused, - struct ib_queue_pair *qp, - struct ib_address_vector *dest __unused, - struct ib_address_vector *source, - struct io_buffer *iobuf, int rc ) { - struct eoib_device *eoib = ib_qp_get_ownerdata ( qp ); - struct net_device *netdev = eoib->netdev; - struct eoib_header *eoib_hdr; - struct ethhdr *ethhdr; - - /* Record errors */ - if ( rc != 0 ) { - netdev_rx_err ( netdev, iobuf, rc ); - return; - } - - /* Sanity check */ - if ( iob_len ( iobuf ) < ( sizeof ( *eoib_hdr ) + sizeof ( *ethhdr ) )){ - DBGC ( eoib, "EoIB %s received packet too short to " - "contain EoIB and Ethernet headers\n", eoib->name ); - DBGC_HD ( eoib, iobuf->data, iob_len ( iobuf ) ); - netdev_rx_err ( netdev, iobuf, -EIO ); - return; - } - if ( ! source ) { - DBGC ( eoib, "EoIB %s received packet without address " - "vector\n", eoib->name ); - netdev_rx_err ( netdev, iobuf, -ENOTTY ); - return; - } - - /* Strip EoIB header */ - iob_pull ( iobuf, sizeof ( *eoib_hdr ) ); - - /* Update neighbour cache entry, if any */ - ethhdr = iobuf->data; - eoib_rx_av ( eoib, ethhdr->h_source, source ); - - /* Hand off to network layer */ - netdev_rx ( netdev, iobuf ); -} - -/** EoIB completion operations */ -static struct ib_completion_queue_operations eoib_cq_op = { - .complete_send = eoib_complete_send, - .complete_recv = eoib_complete_recv, -}; - -/** EoIB queue pair operations */ -static struct ib_queue_pair_operations eoib_qp_op = { - .alloc_iob = alloc_iob, -}; - -/** - * Poll EoIB network device - * - * @v netdev Network device - */ -static void eoib_poll ( struct net_device *netdev ) { - struct eoib_device *eoib = netdev->priv; - struct ib_device *ibdev = eoib->ibdev; - - /* Poll Infiniband device */ - ib_poll_eq ( ibdev ); - - /* Poll the retry timers (required for EoIB multicast join) */ - retry_poll(); -} - -/** - * Handle EoIB broadcast multicast group join completion - * - * @v membership Multicast group membership - * @v rc Status code - */ -static void eoib_join_complete ( struct ib_mc_membership *membership, int rc ) { - struct eoib_device *eoib = - container_of ( membership, struct eoib_device, membership ); - - /* Record join status as link status */ - netdev_link_err ( eoib->netdev, rc ); -} - -/** - * Join EoIB broadcast multicast group - * - * @v eoib EoIB device - * @ret rc Return status code - */ -static int eoib_join_broadcast_group ( struct eoib_device *eoib ) { - int rc; - - /* Join multicast group */ - if ( ( rc = ib_mcast_join ( eoib->ibdev, eoib->qp, - &eoib->membership, &eoib->broadcast, - eoib->mask, eoib_join_complete ) ) != 0 ) { - DBGC ( eoib, "EoIB %s could not join broadcast group: %s\n", - eoib->name, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Leave EoIB broadcast multicast group - * - * @v eoib EoIB device - */ -static void eoib_leave_broadcast_group ( struct eoib_device *eoib ) { - - /* Leave multicast group */ - ib_mcast_leave ( eoib->ibdev, eoib->qp, &eoib->membership ); -} - -/** - * Handle link status change - * - * @v eoib EoIB device - */ -static void eoib_link_state_changed ( struct eoib_device *eoib ) { - struct net_device *netdev = eoib->netdev; - struct ib_device *ibdev = eoib->ibdev; - int rc; - - /* Leave existing broadcast group */ - if ( eoib->qp ) - eoib_leave_broadcast_group ( eoib ); - - /* Update broadcast GID based on potentially-new partition key */ - eoib->broadcast.gid.words[2] = htons ( ibdev->pkey | IB_PKEY_FULL ); - - /* Set net device link state to reflect Infiniband link state */ - rc = ib_link_rc ( ibdev ); - netdev_link_err ( netdev, ( rc ? rc : -EINPROGRESS_JOINING ) ); - - /* Join new broadcast group */ - if ( ib_is_open ( ibdev ) && ib_link_ok ( ibdev ) && eoib->qp && - ( ( rc = eoib_join_broadcast_group ( eoib ) ) != 0 ) ) { - DBGC ( eoib, "EoIB %s could not rejoin broadcast group: " - "%s\n", eoib->name, strerror ( rc ) ); - netdev_link_err ( netdev, rc ); - return; - } -} - -/** - * Open EoIB network device - * - * @v netdev Network device - * @ret rc Return status code - */ -static int eoib_open ( struct net_device *netdev ) { - struct eoib_device *eoib = netdev->priv; - struct ib_device *ibdev = eoib->ibdev; - int rc; - - /* Open IB device */ - if ( ( rc = ib_open ( ibdev ) ) != 0 ) { - DBGC ( eoib, "EoIB %s could not open %s: %s\n", - eoib->name, ibdev->name, strerror ( rc ) ); - goto err_ib_open; - } - - /* Allocate completion queue */ - eoib->cq = ib_create_cq ( ibdev, EOIB_NUM_CQES, &eoib_cq_op ); - if ( ! eoib->cq ) { - DBGC ( eoib, "EoIB %s could not allocate completion queue\n", - eoib->name ); - rc = -ENOMEM; - goto err_create_cq; - } - - /* Allocate queue pair */ - eoib->qp = ib_create_qp ( ibdev, IB_QPT_UD, EOIB_NUM_SEND_WQES, - eoib->cq, EOIB_NUM_RECV_WQES, eoib->cq, - &eoib_qp_op, netdev->name ); - if ( ! eoib->qp ) { - DBGC ( eoib, "EoIB %s could not allocate queue pair\n", - eoib->name ); - rc = -ENOMEM; - goto err_create_qp; - } - ib_qp_set_ownerdata ( eoib->qp, eoib ); - - /* Fill receive rings */ - ib_refill_recv ( ibdev, eoib->qp ); - - /* Fake a link status change to join the broadcast group */ - eoib_link_state_changed ( eoib ); - - return 0; - - ib_destroy_qp ( ibdev, eoib->qp ); - eoib->qp = NULL; - err_create_qp: - ib_destroy_cq ( ibdev, eoib->cq ); - eoib->cq = NULL; - err_create_cq: - ib_close ( ibdev ); - err_ib_open: - return rc; -} - -/** - * Close EoIB network device - * - * @v netdev Network device - */ -static void eoib_close ( struct net_device *netdev ) { - struct eoib_device *eoib = netdev->priv; - struct ib_device *ibdev = eoib->ibdev; - - /* Flush peer cache */ - eoib_flush_peers ( eoib ); - - /* Leave broadcast group */ - eoib_leave_broadcast_group ( eoib ); - - /* Tear down the queues */ - ib_destroy_qp ( ibdev, eoib->qp ); - eoib->qp = NULL; - ib_destroy_cq ( ibdev, eoib->cq ); - eoib->cq = NULL; - - /* Close IB device */ - ib_close ( ibdev ); -} - -/** EoIB network device operations */ -static struct net_device_operations eoib_operations = { - .open = eoib_open, - .close = eoib_close, - .transmit = eoib_transmit, - .poll = eoib_poll, -}; - -/** - * Create EoIB device - * - * @v ibdev Infiniband device - * @v hw_addr Ethernet MAC - * @v broadcast Broadcast address vector - * @v name Interface name (or NULL to use default) - * @ret rc Return status code - */ -int eoib_create ( struct ib_device *ibdev, const uint8_t *hw_addr, - struct ib_address_vector *broadcast, const char *name ) { - struct net_device *netdev; - struct eoib_device *eoib; - int rc; - - /* Allocate network device */ - netdev = alloc_etherdev ( sizeof ( *eoib ) ); - if ( ! netdev ) { - rc = -ENOMEM; - goto err_alloc; - } - netdev_init ( netdev, &eoib_operations ); - eoib = netdev->priv; - netdev->dev = ibdev->dev; - eoib->netdev = netdev; - eoib->ibdev = ibdev_get ( ibdev ); - memcpy ( &eoib->broadcast, broadcast, sizeof ( eoib->broadcast ) ); - INIT_LIST_HEAD ( &eoib->peers ); - - /* Set MAC address */ - memcpy ( netdev->hw_addr, hw_addr, ETH_ALEN ); - - /* Set interface name, if applicable */ - if ( name ) - snprintf ( netdev->name, sizeof ( netdev->name ), "%s", name ); - eoib->name = netdev->name; - - /* Add to list of EoIB devices */ - list_add_tail ( &eoib->list, &eoib_devices ); - - /* Register network device */ - if ( ( rc = register_netdev ( netdev ) ) != 0 ) - goto err_register; - - DBGC ( eoib, "EoIB %s created for %s MAC %s\n", - eoib->name, ibdev->name, eth_ntoa ( hw_addr ) ); - DBGC ( eoib, "EoIB %s broadcast GID " IB_GID_FMT "\n", - eoib->name, IB_GID_ARGS ( &broadcast->gid ) ); - return 0; - - unregister_netdev ( netdev ); - err_register: - list_del ( &eoib->list ); - ibdev_put ( ibdev ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); - err_alloc: - return rc; -} - -/** - * Find EoIB device - * - * @v ibdev Infiniband device - * @v hw_addr Original Ethernet MAC - * @ret eoib EoIB device - */ -struct eoib_device * eoib_find ( struct ib_device *ibdev, - const uint8_t *hw_addr ) { - struct eoib_device *eoib; - - list_for_each_entry ( eoib, &eoib_devices, list ) { - if ( ( eoib->ibdev == ibdev ) && - ( memcmp ( eoib->netdev->hw_addr, hw_addr, - ETH_ALEN ) == 0 ) ) - return eoib; - } - return NULL; -} - -/** - * Remove EoIB device - * - * @v eoib EoIB device - */ -void eoib_destroy ( struct eoib_device *eoib ) { - struct net_device *netdev = eoib->netdev; - - /* Unregister network device */ - unregister_netdev ( netdev ); - - /* Remove from list of network devices */ - list_del ( &eoib->list ); - - /* Drop reference to Infiniband device */ - ibdev_put ( eoib->ibdev ); - - /* Free network device */ - DBGC ( eoib, "EoIB %s destroyed\n", eoib->name ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} - -/** - * Probe EoIB device - * - * @v ibdev Infiniband device - * @ret rc Return status code - */ -static int eoib_probe ( struct ib_device *ibdev __unused ) { - - /* EoIB devices are not created automatically */ - return 0; -} - -/** - * Handle device or link status change - * - * @v ibdev Infiniband device - */ -static void eoib_notify ( struct ib_device *ibdev ) { - struct eoib_device *eoib; - - /* Handle link status change for any attached EoIB devices */ - list_for_each_entry ( eoib, &eoib_devices, list ) { - if ( eoib->ibdev != ibdev ) - continue; - eoib_link_state_changed ( eoib ); - } -} - -/** - * Remove EoIB device - * - * @v ibdev Infiniband device - */ -static void eoib_remove ( struct ib_device *ibdev ) { - struct eoib_device *eoib; - struct eoib_device *tmp; - - /* Remove any attached EoIB devices */ - list_for_each_entry_safe ( eoib, tmp, &eoib_devices, list ) { - if ( eoib->ibdev != ibdev ) - continue; - eoib_destroy ( eoib ); - } -} - -/** EoIB driver */ -struct ib_driver eoib_driver __ib_driver = { - .name = "EoIB", - .probe = eoib_probe, - .notify = eoib_notify, - .remove = eoib_remove, -}; - -/**************************************************************************** - * - * EoIB heartbeat packets - * - **************************************************************************** - */ - -/** - * Silently ignore incoming EoIB heartbeat packets - * - * @v iobuf I/O buffer - * @v netdev Network device - * @v ll_source Link-layer source address - * @v flags Packet flags - * @ret rc Return status code - */ -static int eoib_heartbeat_rx ( struct io_buffer *iobuf, - struct net_device *netdev __unused, - const void *ll_dest __unused, - const void *ll_source __unused, - unsigned int flags __unused ) { - free_iob ( iobuf ); - return 0; -} - -/** - * Transcribe EoIB heartbeat address - * - * @v net_addr EoIB heartbeat address - * @ret string "<EoIB>" - * - * This operation is meaningless for the EoIB heartbeat protocol. - */ -static const char * eoib_heartbeat_ntoa ( const void *net_addr __unused ) { - return "<EoIB>"; -} - -/** EoIB heartbeat network protocol */ -struct net_protocol eoib_heartbeat_protocol __net_protocol = { - .name = "EoIB", - .net_proto = htons ( EOIB_MAGIC ), - .rx = eoib_heartbeat_rx, - .ntoa = eoib_heartbeat_ntoa, -}; - -/**************************************************************************** - * - * EoIB gateway - * - **************************************************************************** - * - * Some dubious EoIB implementations require all broadcast traffic to - * be sent twice: once to the actual broadcast group, and once as a - * unicast to the EoIB-to-Ethernet gateway. This somewhat curious - * design arises since the EoIB-to-Ethernet gateway hardware lacks the - * ability to attach a queue pair to a multicast GID (or LID), and so - * cannot receive traffic sent to the broadcast group. - * - */ - -/** - * Transmit duplicate packet to the EoIB gateway - * - * @v eoib EoIB device - * @v original Original I/O buffer - */ -static void eoib_duplicate ( struct eoib_device *eoib, - struct io_buffer *original ) { - struct net_device *netdev = eoib->netdev; - struct ib_device *ibdev = eoib->ibdev; - struct ib_address_vector *av = &eoib->gateway; - size_t len = iob_len ( original ); - struct io_buffer *copy; - int rc; - - /* Create copy of I/O buffer */ - copy = alloc_iob ( len ); - if ( ! copy ) { - rc = -ENOMEM; - goto err_alloc; - } - memcpy ( iob_put ( copy, len ), original->data, len ); - - /* Append to network device's transmit queue */ - list_add_tail ( ©->list, &original->list ); - - /* Resolve path to gateway */ - if ( ( rc = ib_resolve_path ( ibdev, av ) ) != 0 ) { - DBGC ( eoib, "EoIB %s no path to gateway: %s\n", - eoib->name, strerror ( rc ) ); - goto err_path; - } - - /* Force use of GRH even for local destinations */ - av->gid_present = 1; - - /* Post send work queue entry */ - if ( ( rc = ib_post_send ( eoib->ibdev, eoib->qp, av, copy ) ) != 0 ) - goto err_post_send; - - return; - - err_post_send: - err_path: - err_alloc: - netdev_tx_complete_err ( netdev, copy, rc ); -} - -/** - * Set EoIB gateway - * - * @v eoib EoIB device - * @v av Address vector, or NULL to clear gateway - */ -void eoib_set_gateway ( struct eoib_device *eoib, - struct ib_address_vector *av ) { - - if ( av ) { - DBGC ( eoib, "EoIB %s using gateway " IB_GID_FMT "\n", - eoib->name, IB_GID_ARGS ( &av->gid ) ); - memcpy ( &eoib->gateway, av, sizeof ( eoib->gateway ) ); - eoib->duplicate = eoib_duplicate; - } else { - DBGC ( eoib, "EoIB %s not using gateway\n", eoib->name ); - eoib->duplicate = NULL; - } -} diff --git a/roms/ipxe/src/drivers/net/etherfabric.c b/roms/ipxe/src/drivers/net/etherfabric.c index 2cd41d4ca..29d117443 100644 --- a/roms/ipxe/src/drivers/net/etherfabric.c +++ b/roms/ipxe/src/drivers/net/etherfabric.c @@ -4006,7 +4006,7 @@ efab_init_mac ( struct efab_nic *efab ) * because we want to use it, or because we're about * to reset the mac anyway */ - mdelay ( 2000 ); + sleep ( 2 ); if ( ! efab->link_up ) { EFAB_ERR ( "!\n" ); diff --git a/roms/ipxe/src/drivers/net/intel.c b/roms/ipxe/src/drivers/net/intel.c index 127f5c7e7..6309e9aa5 100644 --- a/roms/ipxe/src/drivers/net/intel.c +++ b/roms/ipxe/src/drivers/net/intel.c @@ -295,23 +295,14 @@ static int intel_reset ( struct intel_nic *intel ) { writel ( ctrl, intel->regs + INTEL_CTRL ); mdelay ( INTEL_RESET_DELAY_MS ); - /* On some models (notably ICH), the PHY reset mechanism - * appears to be broken. In particular, the PHY_CTRL register - * will be correctly loaded from NVM but the values will not - * be propagated to the "OEM bits" PHY register. This - * typically has the effect of dropping the link speed to - * 10Mbps. - * - * Work around this problem by skipping the PHY reset if - * either (a) the link is already up, or (b) this particular - * NIC is known to be broken. + /* If link is already up, do not attempt to reset the PHY. On + * some models (notably ICH), performing a PHY reset seems to + * drop the link speed to 10Mbps. */ status = readl ( intel->regs + INTEL_STATUS ); - if ( ( intel->flags & INTEL_NO_PHY_RST ) || - ( status & INTEL_STATUS_LU ) ) { - DBGC ( intel, "INTEL %p %sMAC reset (ctrl %08x)\n", intel, - ( ( intel->flags & INTEL_NO_PHY_RST ) ? "forced " : "" ), - ctrl ); + if ( status & INTEL_STATUS_LU ) { + DBGC ( intel, "INTEL %p MAC reset (ctrl %08x)\n", + intel, ctrl ); return 0; } @@ -1038,7 +1029,7 @@ static struct pci_device_id intel_nics[] = { PCI_ROM ( 0x8086, 0x10f5, "82567lm", "82567LM", 0 ), PCI_ROM ( 0x8086, 0x10f6, "82574l", "82574L", 0 ), PCI_ROM ( 0x8086, 0x1501, "82567v-3", "82567V-3", INTEL_PBS_ERRATA ), - PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", INTEL_NO_PHY_RST ), + PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", 0 ), PCI_ROM ( 0x8086, 0x1503, "82579v", "82579V", 0 ), PCI_ROM ( 0x8086, 0x150a, "82576ns", "82576NS", 0 ), PCI_ROM ( 0x8086, 0x150c, "82583v", "82583V", 0 ), @@ -1057,18 +1048,14 @@ static struct pci_device_id intel_nics[] = { PCI_ROM ( 0x8086, 0x1526, "82576-5", "82576", 0 ), PCI_ROM ( 0x8086, 0x1527, "82580-f2", "82580 Fiber", 0 ), PCI_ROM ( 0x8086, 0x1533, "i210", "I210", 0 ), - PCI_ROM ( 0x8086, 0x1539, "i211", "I211", 0 ), - PCI_ROM ( 0x8086, 0x153a, "i217lm", "I217-LM", INTEL_NO_PHY_RST ), + PCI_ROM ( 0x8086, 0x153a, "i217lm", "I217-LM", 0 ), PCI_ROM ( 0x8086, 0x153b, "i217v", "I217-V", 0 ), PCI_ROM ( 0x8086, 0x1559, "i218v", "I218-V", 0), PCI_ROM ( 0x8086, 0x155a, "i218lm", "I218-LM", 0), - PCI_ROM ( 0x8086, 0x157b, "i210-2", "I210", 0 ), - PCI_ROM ( 0x8086, 0x15a0, "i218lm-2", "I218-LM", INTEL_NO_PHY_RST ), + PCI_ROM ( 0x8086, 0x15a0, "i218lm-2", "I218-LM", 0 ), PCI_ROM ( 0x8086, 0x15a1, "i218v-2", "I218-V", 0 ), - PCI_ROM ( 0x8086, 0x15a2, "i218lm-3", "I218-LM", INTEL_NO_PHY_RST ), - PCI_ROM ( 0x8086, 0x15a3, "i218v-3", "I218-V", INTEL_NO_PHY_RST ), - PCI_ROM ( 0x8086, 0x15b7, "i219lm-2", "I219-LM (2)", 0 ), - PCI_ROM ( 0x8086, 0x15b8, "i219v-2", "I219-V (2)", 0 ), + PCI_ROM ( 0x8086, 0x15a2, "i218lm-3", "I218-LM", 0 ), + PCI_ROM ( 0x8086, 0x15a3, "i218v-3", "I218-V", 0 ), PCI_ROM ( 0x8086, 0x294c, "82566dc-2", "82566DC-2", 0 ), PCI_ROM ( 0x8086, 0x2e6e, "cemedia", "CE Media Processor", 0 ), }; diff --git a/roms/ipxe/src/drivers/net/intel.h b/roms/ipxe/src/drivers/net/intel.h index 16a72a11b..ce9e3f467 100644 --- a/roms/ipxe/src/drivers/net/intel.h +++ b/roms/ipxe/src/drivers/net/intel.h @@ -99,8 +99,8 @@ struct intel_descriptor { #define INTEL_IRQ_TXQE 0x00000002UL /**< Transmit queue empty */ #define INTEL_IRQ_LSC 0x00000004UL /**< Link status change */ #define INTEL_IRQ_RXDMT0 0x00000010UL /**< Receive queue low */ -#define INTEL_IRQ_RXO 0x00000040UL /**< Receive overrun */ #define INTEL_IRQ_RXT0 0x00000080UL /**< Receive timer */ +#define INTEL_IRQ_RXO 0x00000400UL /**< Receive overrun */ /** Interrupt Mask Set/Read Register */ #define INTEL_IMS 0x000d0UL @@ -301,8 +301,6 @@ enum intel_flags { INTEL_PBS_ERRATA = 0x0001, /** VMware missing interrupt workaround required */ INTEL_VMWARE = 0x0002, - /** PHY reset is broken */ - INTEL_NO_PHY_RST = 0x0004, }; /** diff --git a/roms/ipxe/src/drivers/net/ipoib.c b/roms/ipxe/src/drivers/net/ipoib.c index 8a65c87ba..6552d764e 100644 --- a/roms/ipxe/src/drivers/net/ipoib.c +++ b/roms/ipxe/src/drivers/net/ipoib.c @@ -65,23 +65,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); "Missing REMAC for IPv4 packet (ARP sent)" ) /** Number of IPoIB send work queue entries */ -#define IPOIB_NUM_SEND_WQES 8 +#define IPOIB_NUM_SEND_WQES 2 /** Number of IPoIB receive work queue entries */ #define IPOIB_NUM_RECV_WQES 4 /** Number of IPoIB completion entries */ -#define IPOIB_NUM_CQES 16 - -/** An IPoIB broadcast address */ -struct ipoib_broadcast { - /** MAC address */ - struct ipoib_mac mac; - /** Address vector */ - struct ib_address_vector av; - /** Multicast group membership */ - struct ib_mc_membership membership; -}; +#define IPOIB_NUM_CQES 8 /** An IPoIB device */ struct ipoib_device { @@ -89,16 +79,22 @@ struct ipoib_device { struct net_device *netdev; /** Underlying Infiniband device */ struct ib_device *ibdev; - /** List of IPoIB devices */ - struct list_head list; /** Completion queue */ struct ib_completion_queue *cq; /** Queue pair */ struct ib_queue_pair *qp; /** Local MAC */ struct ipoib_mac mac; - /** Broadcast address */ - struct ipoib_broadcast broadcast; + /** Broadcast MAC */ + struct ipoib_mac broadcast; + /** Joined to IPv4 broadcast multicast group + * + * This flag indicates whether or not we have initiated the + * join to the IPv4 broadcast multicast group. + */ + int broadcast_joined; + /** IPv4 broadcast multicast group membership */ + struct ib_mc_membership broadcast_membership; /** REMAC cache */ struct list_head peers; }; @@ -120,9 +116,6 @@ struct errortab ipoib_errors[] __errortab = { __einfo_errortab ( EINFO_EINPROGRESS_JOINING ), }; -/** List of all IPoIB devices */ -static LIST_HEAD ( ipoib_devices ); - static struct net_device_operations ipoib_operations; /**************************************************************************** @@ -157,7 +150,7 @@ static struct ipoib_mac * ipoib_find_remac ( struct ipoib_device *ipoib, * multicasts as broadcasts for simplicity. */ if ( is_multicast_ether_addr ( remac ) ) - return &ipoib->broadcast.mac; + return &ipoib->broadcast; /* Try to find via REMAC cache */ list_for_each_entry ( peer, &ipoib->peers, list ) { @@ -503,10 +496,8 @@ static int ipoib_transmit ( struct net_device *netdev, struct ethhdr *ethhdr; struct iphdr *iphdr; struct ipoib_hdr *ipoib_hdr; - struct ipoib_remac *remac; struct ipoib_mac *mac; - struct ib_address_vector *dest; - struct ib_address_vector av; + struct ib_address_vector dest; uint16_t net_proto; int rc; @@ -524,32 +515,12 @@ static int ipoib_transmit ( struct net_device *netdev, /* Strip eIPoIB header */ ethhdr = iobuf->data; - remac = ( ( struct ipoib_remac * ) ethhdr->h_dest ); net_proto = ethhdr->h_protocol; iob_pull ( iobuf, sizeof ( *ethhdr ) ); /* Identify destination address */ - if ( is_multicast_ether_addr ( remac ) ) { - - /* Transmit multicasts as broadcasts, for simplicity */ - dest = &ipoib->broadcast.av; - - } else if ( ( mac = ipoib_find_remac ( ipoib, remac ) ) ) { - - /* Construct address vector from IPoIB MAC */ - dest = &av; - memset ( dest, 0, sizeof ( *dest ) ); - dest->qpn = ( ntohl ( mac->flags__qpn ) & IB_QPN_MASK ); - dest->qkey = ipoib->broadcast.av.qkey; - dest->gid_present = 1; - memcpy ( &dest->gid, &mac->gid, sizeof ( dest->gid ) ); - if ( ( rc = ib_resolve_path ( ibdev, dest ) ) != 0 ) { - /* Path not resolved yet */ - return rc; - } - - } else { - + mac = ipoib_find_remac ( ipoib, ( ( void * ) ethhdr->h_dest ) ); + if ( ! mac ) { /* Generate a new ARP request (if possible) to trigger * population of the REMAC cache entry. */ @@ -586,8 +557,17 @@ static int ipoib_transmit ( struct net_device *netdev, ipoib_hdr->proto = net_proto; ipoib_hdr->reserved = 0; - /* Transmit packet */ - return ib_post_send ( ibdev, ipoib->qp, dest, iobuf ); + /* Construct address vector */ + memset ( &dest, 0, sizeof ( dest ) ); + dest.qpn = ( ntohl ( mac->flags__qpn ) & IB_QPN_MASK ); + dest.gid_present = 1; + memcpy ( &dest.gid, &mac->gid, sizeof ( dest.gid ) ); + if ( ( rc = ib_resolve_path ( ibdev, &dest ) ) != 0 ) { + /* Path not resolved yet */ + return rc; + } + + return ib_post_send ( ibdev, ipoib->qp, &dest, iobuf ); } /** @@ -671,8 +651,9 @@ static void ipoib_complete_recv ( struct ib_device *ibdev __unused, ethhdr->h_protocol = net_proto; /* Construct destination address */ - if ( dest->gid_present && IB_GID_MULTICAST ( &dest->gid ) ) { - /* Multicast GID: use the Ethernet broadcast address */ + if ( dest->gid_present && ( memcmp ( &dest->gid, &ipoib->broadcast.gid, + sizeof ( dest->gid ) ) == 0 ) ) { + /* Broadcast GID; use the Ethernet broadcast address */ memcpy ( ðhdr->h_dest, eth_broadcast, sizeof ( ethhdr->h_dest ) ); } else { @@ -746,13 +727,18 @@ static void ipoib_poll ( struct net_device *netdev ) { /** * Handle IPv4 broadcast multicast group join completion * + * @v ibdev Infiniband device + * @v qp Queue pair * @v membership Multicast group membership * @v rc Status code + * @v mad Response MAD (or NULL on error) */ -void ipoib_join_complete ( struct ib_mc_membership *membership, int rc ) { +void ipoib_join_complete ( struct ib_device *ibdev __unused, + struct ib_queue_pair *qp __unused, + struct ib_mc_membership *membership, int rc, + union ib_mad *mad __unused ) { struct ipoib_device *ipoib = container_of ( membership, - struct ipoib_device, - broadcast.membership ); + struct ipoib_device, broadcast_membership ); /* Record join status as link status */ netdev_link_err ( ipoib->netdev, rc ); @@ -767,15 +753,15 @@ void ipoib_join_complete ( struct ib_mc_membership *membership, int rc ) { static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) { int rc; - /* Join multicast group */ if ( ( rc = ib_mcast_join ( ipoib->ibdev, ipoib->qp, - &ipoib->broadcast.membership, - &ipoib->broadcast.av, 0, + &ipoib->broadcast_membership, + &ipoib->broadcast.gid, ipoib_join_complete ) ) != 0 ) { DBGC ( ipoib, "IPoIB %p could not join broadcast group: %s\n", ipoib, strerror ( rc ) ); return rc; } + ipoib->broadcast_joined = 1; return 0; } @@ -787,19 +773,21 @@ static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) { */ static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) { - /* Leave multicast group */ - ib_mcast_leave ( ipoib->ibdev, ipoib->qp, - &ipoib->broadcast.membership ); + if ( ipoib->broadcast_joined ) { + ib_mcast_leave ( ipoib->ibdev, ipoib->qp, + &ipoib->broadcast_membership ); + ipoib->broadcast_joined = 0; + } } /** * Handle link status change * - * @v ipoib IPoIB device + * @v ibdev Infiniband device */ -static void ipoib_link_state_changed ( struct ipoib_device *ipoib ) { - struct ib_device *ibdev = ipoib->ibdev; - struct net_device *netdev = ipoib->netdev; +static void ipoib_link_state_changed ( struct ib_device *ibdev ) { + struct net_device *netdev = ib_get_ownerdata ( ibdev ); + struct ipoib_device *ipoib = netdev->priv; int rc; /* Leave existing broadcast group */ @@ -810,17 +798,10 @@ static void ipoib_link_state_changed ( struct ipoib_device *ipoib ) { memcpy ( &ipoib->mac.gid.s.prefix, &ibdev->gid.s.prefix, sizeof ( ipoib->mac.gid.s.prefix ) ); - /* Update broadcast MAC GID based on potentially-new partition key */ - ipoib->broadcast.mac.gid.words[2] = + /* Update broadcast GID based on potentially-new partition key */ + ipoib->broadcast.gid.words[2] = htons ( ibdev->pkey | IB_PKEY_FULL ); - /* Construct broadcast address vector from broadcast MAC address */ - memset ( &ipoib->broadcast.av, 0, sizeof ( ipoib->broadcast.av ) ); - ipoib->broadcast.av.qpn = IB_QPN_BROADCAST; - ipoib->broadcast.av.gid_present = 1; - memcpy ( &ipoib->broadcast.av.gid, &ipoib->broadcast.mac.gid, - sizeof ( ipoib->broadcast.av.gid ) ); - /* Set net device link state to reflect Infiniband link state */ rc = ib_link_rc ( ibdev ); netdev_link_err ( netdev, ( rc ? rc : -EINPROGRESS_JOINING ) ); @@ -865,7 +846,7 @@ static int ipoib_open ( struct net_device *netdev ) { /* Allocate queue pair */ ipoib->qp = ib_create_qp ( ibdev, IB_QPT_UD, IPOIB_NUM_SEND_WQES, ipoib->cq, IPOIB_NUM_RECV_WQES, ipoib->cq, - &ipoib_qp_op, netdev->name ); + &ipoib_qp_op ); if ( ! ipoib->qp ) { DBGC ( ipoib, "IPoIB %p could not allocate queue pair\n", ipoib ); @@ -881,7 +862,7 @@ static int ipoib_open ( struct net_device *netdev ) { ib_refill_recv ( ibdev, ipoib->qp ); /* Fake a link status change to join the broadcast group */ - ipoib_link_state_changed ( ipoib ); + ipoib_link_state_changed ( ibdev ); return 0; @@ -947,6 +928,7 @@ static int ipoib_probe ( struct ib_device *ibdev ) { return -ENOMEM; netdev_init ( netdev, &ipoib_operations ); ipoib = netdev->priv; + ib_set_ownerdata ( ibdev, netdev ); netdev->dev = ibdev->dev; memset ( ipoib, 0, sizeof ( *ipoib ) ); ipoib->netdev = netdev; @@ -956,18 +938,14 @@ static int ipoib_probe ( struct ib_device *ibdev ) { /* Extract hardware address */ memcpy ( netdev->hw_addr, &ibdev->gid.s.guid, sizeof ( ibdev->gid.s.guid ) ); - memcpy ( netdev->ll_addr, ibdev->lemac, ETH_ALEN ); /* Set local MAC address */ memcpy ( &ipoib->mac.gid.s.guid, &ibdev->gid.s.guid, sizeof ( ipoib->mac.gid.s.guid ) ); /* Set default broadcast MAC address */ - memcpy ( &ipoib->broadcast.mac, &ipoib_broadcast, - sizeof ( ipoib->broadcast.mac ) ); - - /* Add to list of IPoIB devices */ - list_add_tail ( &ipoib->list, &ipoib_devices ); + memcpy ( &ipoib->broadcast, &ipoib_broadcast, + sizeof ( ipoib->broadcast ) ); /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) @@ -975,74 +953,29 @@ static int ipoib_probe ( struct ib_device *ibdev ) { return 0; - unregister_netdev ( netdev ); err_register_netdev: - list_del ( &ipoib->list ); netdev_nullify ( netdev ); netdev_put ( netdev ); return rc; } /** - * Handle device or link status change - * - * @v ibdev Infiniband device - */ -static void ipoib_notify ( struct ib_device *ibdev ) { - struct ipoib_device *ipoib; - - /* Handle link status change for any attached IPoIB devices */ - list_for_each_entry ( ipoib, &ipoib_devices, list ) { - if ( ipoib->ibdev != ibdev ) - continue; - ipoib_link_state_changed ( ipoib ); - } -} - -/** * Remove IPoIB device * * @v ibdev Infiniband device */ static void ipoib_remove ( struct ib_device *ibdev ) { - struct ipoib_device *ipoib; - struct ipoib_device *tmp; - struct net_device *netdev; + struct net_device *netdev = ib_get_ownerdata ( ibdev ); - /* Remove any attached IPoIB devices */ - list_for_each_entry_safe ( ipoib, tmp, &ipoib_devices, list ) { - if ( ipoib->ibdev != ibdev ) - continue; - netdev = ipoib->netdev; - unregister_netdev ( netdev ); - list_del ( &ipoib->list ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); - } + unregister_netdev ( netdev ); + netdev_nullify ( netdev ); + netdev_put ( netdev ); } /** IPoIB driver */ struct ib_driver ipoib_driver __ib_driver = { .name = "IPoIB", .probe = ipoib_probe, - .notify = ipoib_notify, + .notify = ipoib_link_state_changed, .remove = ipoib_remove, }; - -/** - * Find IPoIB network device - * - * @v ibdev Infiniband device - * @ret netdev IPoIB network device, or NULL if not found - */ -struct net_device * ipoib_netdev ( struct ib_device *ibdev ) { - struct ipoib_device *ipoib; - - /* Find matching IPoIB device */ - list_for_each_entry ( ipoib, &ipoib_devices, list ) { - if ( ipoib->ibdev != ibdev ) - continue; - return ipoib->netdev; - } - return NULL; -} diff --git a/roms/ipxe/src/drivers/net/ncm.c b/roms/ipxe/src/drivers/net/ncm.c index 1837291f7..10728d2a1 100644 --- a/roms/ipxe/src/drivers/net/ncm.c +++ b/roms/ipxe/src/drivers/net/ncm.c @@ -186,7 +186,7 @@ static int ncm_in_prefill ( struct ncm_device *ncm ) { count = NCM_IN_MIN_COUNT; if ( ( count * mtu ) > NCM_IN_MAX_SIZE ) continue; - usb_refill_init ( &ncm->usbnet.in, 0, mtu, count ); + usb_refill_init ( &ncm->usbnet.in, mtu, count ); if ( ( rc = usb_prefill ( &ncm->usbnet.in ) ) != 0 ) { DBGC ( ncm, "NCM %p could not prefill %dx %zd-byte " "buffers for bulk IN\n", ncm, count, mtu ); @@ -453,15 +453,6 @@ static int ncm_open ( struct net_device *netdev ) { goto err_set_ntb_input_size; } - /* Set MAC address */ - if ( ( rc = usb_control ( usb, NCM_SET_NET_ADDRESS, 0, - ncm->usbnet.comms, netdev->ll_addr, - netdev->ll_protocol->ll_addr_len ) ) != 0 ) { - DBGC ( ncm, "NCM %p could not set MAC address: %s\n", - ncm, strerror ( rc ) ); - /* Ignore error and continue */ - } - /* Open USB network device */ if ( ( rc = usbnet_open ( &ncm->usbnet ) ) != 0 ) { DBGC ( ncm, "NCM %p could not open: %s\n", @@ -575,7 +566,7 @@ static int ncm_probe ( struct usb_function *func, ncm->netdev = netdev; usbnet_init ( &ncm->usbnet, func, &ncm_intr_operations, &ncm_in_operations, &ncm_out_operations ); - usb_refill_init ( &ncm->usbnet.intr, 0, 0, NCM_INTR_COUNT ); + usb_refill_init ( &ncm->usbnet.intr, 0, NCM_INTR_COUNT ); DBGC ( ncm, "NCM %p on %s\n", ncm, func->name ); /* Describe USB network device */ @@ -664,6 +655,11 @@ static struct usb_device_id ncm_ids[] = { .name = "cdc-ncm", .vendor = USB_ANY_ID, .product = USB_ANY_ID, + .class = { + .class = USB_CLASS_CDC, + .subclass = USB_SUBCLASS_CDC_NCM, + .protocol = 0, + }, }, }; @@ -671,8 +667,6 @@ static struct usb_device_id ncm_ids[] = { struct usb_driver ncm_driver __usb_driver = { .ids = ncm_ids, .id_count = ( sizeof ( ncm_ids ) / sizeof ( ncm_ids[0] ) ), - .class = USB_CLASS_ID ( USB_CLASS_CDC, USB_SUBCLASS_CDC_NCM, 0 ), - .score = USB_SCORE_NORMAL, .probe = ncm_probe, .remove = ncm_remove, }; diff --git a/roms/ipxe/src/drivers/net/ncm.h b/roms/ipxe/src/drivers/net/ncm.h index 6b0d21cdb..a9565a56b 100644 --- a/roms/ipxe/src/drivers/net/ncm.h +++ b/roms/ipxe/src/drivers/net/ncm.h @@ -51,11 +51,6 @@ struct ncm_ntb_parameters { uint16_t max; } __attribute__ (( packed )); -/** Set MAC address */ -#define NCM_SET_NET_ADDRESS \ - ( USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE | \ - USB_REQUEST_TYPE ( 0x82 ) ) - /** Set NTB input size */ #define NCM_SET_NTB_INPUT_SIZE \ ( USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE | \ diff --git a/roms/ipxe/src/drivers/net/phantom/phantom.c b/roms/ipxe/src/drivers/net/phantom/phantom.c index 781049ff4..38b66743c 100644 --- a/roms/ipxe/src/drivers/net/phantom/phantom.c +++ b/roms/ipxe/src/drivers/net/phantom/phantom.c @@ -2060,7 +2060,6 @@ static int phantom_probe ( struct pci_device *pci ) { struct net_device *netdev; struct phantom_nic *phantom; struct settings *parent_settings; - unsigned int busdevfn; int rc; /* Allocate Phantom device */ @@ -2091,20 +2090,19 @@ static int phantom_probe ( struct pci_device *pci ) { * B2 will have this fixed; remove this hack when B1 is no * longer in use. */ - busdevfn = pci->busdevfn; - if ( PCI_FUNC ( busdevfn ) == 0 ) { + if ( PCI_FUNC ( pci->busdevfn ) == 0 ) { unsigned int i; for ( i = 0 ; i < 8 ; i++ ) { uint32_t temp; pci->busdevfn = - PCI_BUSDEVFN ( PCI_SEG ( busdevfn ), - PCI_BUS ( busdevfn ), - PCI_SLOT ( busdevfn ), i ); + PCI_BUSDEVFN ( PCI_BUS ( pci->busdevfn ), + PCI_SLOT ( pci->busdevfn ), i ); pci_read_config_dword ( pci, 0xc8, &temp ); pci_read_config_dword ( pci, 0xc8, &temp ); pci_write_config_dword ( pci, 0xc8, 0xf1000 ); } - pci->busdevfn = busdevfn; + pci->busdevfn = PCI_BUSDEVFN ( PCI_BUS ( pci->busdevfn ), + PCI_SLOT ( pci->busdevfn ), 0 ); } /* Initialise the command PEG */ diff --git a/roms/ipxe/src/drivers/net/sis190.c b/roms/ipxe/src/drivers/net/sis190.c index 81f3d9844..991c30f9e 100644 --- a/roms/ipxe/src/drivers/net/sis190.c +++ b/roms/ipxe/src/drivers/net/sis190.c @@ -72,6 +72,12 @@ struct pci_driver sis190_isa_bridge_driver __pci_driver = { static const u32 sis190_intr_mask = RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange; +/* + * Maximum number of multicast addresses to filter (vs. Rx-all-multicast). + * The chips use a 64 element hash table based on the Ethernet CRC. + */ +static const int multicast_filter_limit = 32; + static void __mdio_cmd(void *ioaddr, u32 ctl) { unsigned int i; diff --git a/roms/ipxe/src/drivers/net/sis190.h b/roms/ipxe/src/drivers/net/sis190.h index 79f94d2d9..0551333d5 100644 --- a/roms/ipxe/src/drivers/net/sis190.h +++ b/roms/ipxe/src/drivers/net/sis190.h @@ -297,6 +297,13 @@ static struct mii_chip_info { { NULL, { 0x00, 0x00 }, 0, 0 } }; +static const struct { + const char *name; +} sis_chip_info[] = { + { "SiS 190 PCI Fast Ethernet adapter" }, + { "SiS 191 PCI Gigabit Ethernet adapter" }, +}; + static void sis190_phy_task(struct sis190_private *tp); static void sis190_free(struct net_device *dev); static inline void sis190_init_rxfilter(struct net_device *dev); diff --git a/roms/ipxe/src/drivers/net/skge.c b/roms/ipxe/src/drivers/net/skge.c index c3264225b..6384e7647 100755 --- a/roms/ipxe/src/drivers/net/skge.c +++ b/roms/ipxe/src/drivers/net/skge.c @@ -84,6 +84,9 @@ static struct net_device_operations skge_operations = { /* Avoid conditionals by using array */ static const int txqaddr[] = { Q_XA1, Q_XA2 }; static const int rxqaddr[] = { Q_R1, Q_R2 }; +static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F }; +static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; +static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F }; static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 }; /* Determine supported/advertised modes based on hardware. @@ -1919,6 +1922,8 @@ static void skge_tx_clean(struct net_device *dev) skge->tx_ring.to_clean = e; } +static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 }; + static inline u16 phy_length(const struct skge_hw *hw, u32 status) { if (hw->chip_id == CHIP_ID_GENESIS) diff --git a/roms/ipxe/src/drivers/net/smsc75xx.c b/roms/ipxe/src/drivers/net/smsc75xx.c index 4ce98ac80..017e02a59 100644 --- a/roms/ipxe/src/drivers/net/smsc75xx.c +++ b/roms/ipxe/src/drivers/net/smsc75xx.c @@ -511,7 +511,6 @@ static int smsc75xx_dump_statistics ( struct smsc75xx_device *smsc75xx ) { */ static int smsc75xx_reset ( struct smsc75xx_device *smsc75xx ) { uint32_t hw_cfg; - unsigned int i; int rc; /* Reset device */ @@ -520,22 +519,18 @@ static int smsc75xx_reset ( struct smsc75xx_device *smsc75xx ) { return rc; /* Wait for reset to complete */ - for ( i = 0 ; i < SMSC75XX_RESET_MAX_WAIT_MS ; i++ ) { + udelay ( SMSC75XX_RESET_DELAY_US ); - /* Check if reset has completed */ - if ( ( rc = smsc75xx_readl ( smsc75xx, SMSC75XX_HW_CFG, - &hw_cfg ) ) != 0 ) - return rc; - if ( ! ( hw_cfg & SMSC75XX_HW_CFG_LRST ) ) - return 0; - - /* Delay */ - mdelay ( 1 ); + /* Check that reset has completed */ + if ( ( rc = smsc75xx_readl ( smsc75xx, SMSC75XX_HW_CFG, + &hw_cfg ) ) != 0 ) + return rc; + if ( hw_cfg & SMSC75XX_HW_CFG_LRST ) { + DBGC ( smsc75xx, "SMSC75XX %p failed to reset\n", smsc75xx ); + return -ETIMEDOUT; } - DBGC ( smsc75xx, "SMSC75XX %p timed out waiting for reset\n", - smsc75xx ); - return -ETIMEDOUT; + return 0; } /****************************************************************************** @@ -984,9 +979,8 @@ static int smsc75xx_probe ( struct usb_function *func, smsc75xx->netdev = netdev; usbnet_init ( &smsc75xx->usbnet, func, &smsc75xx_intr_operations, &smsc75xx_in_operations, &smsc75xx_out_operations ); - usb_refill_init ( &smsc75xx->usbnet.intr, 0, 0, - SMSC75XX_INTR_MAX_FILL ); - usb_refill_init ( &smsc75xx->usbnet.in, 0, SMSC75XX_IN_MTU, + usb_refill_init ( &smsc75xx->usbnet.intr, 0, SMSC75XX_INTR_MAX_FILL ); + usb_refill_init ( &smsc75xx->usbnet.in, SMSC75XX_IN_MTU, SMSC75XX_IN_MAX_FILL ); mii_init ( &smsc75xx->mii, &smsc75xx_mii_operations ); DBGC ( smsc75xx, "SMSC75XX %p on %s\n", smsc75xx, func->name ); @@ -1044,11 +1038,13 @@ static struct usb_device_id smsc75xx_ids[] = { .name = "smsc7500", .vendor = 0x0424, .product = 0x7500, + .class = { 0xff, 0x00, 0xff }, }, { .name = "smsc7505", .vendor = 0x0424, .product = 0x7505, + .class = { 0xff, 0x00, 0xff }, }, }; @@ -1056,8 +1052,6 @@ static struct usb_device_id smsc75xx_ids[] = { struct usb_driver smsc75xx_driver __usb_driver = { .ids = smsc75xx_ids, .id_count = ( sizeof ( smsc75xx_ids ) / sizeof ( smsc75xx_ids[0] ) ), - .class = USB_CLASS_ID ( 0xff, 0x00, 0xff ), - .score = USB_SCORE_NORMAL, .probe = smsc75xx_probe, .remove = smsc75xx_remove, }; diff --git a/roms/ipxe/src/drivers/net/smsc75xx.h b/roms/ipxe/src/drivers/net/smsc75xx.h index ae81fc168..2463b72a1 100644 --- a/roms/ipxe/src/drivers/net/smsc75xx.h +++ b/roms/ipxe/src/drivers/net/smsc75xx.h @@ -280,8 +280,8 @@ struct smsc75xx_device { uint32_t int_sts; }; -/** Maximum time to wait for reset (in milliseconds) */ -#define SMSC75XX_RESET_MAX_WAIT_MS 100 +/** Reset delay (in microseconds) */ +#define SMSC75XX_RESET_DELAY_US 2 /** Maximum time to wait for EEPROM (in milliseconds) */ #define SMSC75XX_EEPROM_MAX_WAIT_MS 100 diff --git a/roms/ipxe/src/drivers/net/smsc95xx.c b/roms/ipxe/src/drivers/net/smsc95xx.c deleted file mode 100644 index 3d9c0f1aa..000000000 --- a/roms/ipxe/src/drivers/net/smsc95xx.c +++ /dev/null @@ -1,1300 +0,0 @@ -/* - * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <byteswap.h> -#include <ipxe/ethernet.h> -#include <ipxe/usb.h> -#include <ipxe/usbnet.h> -#include <ipxe/profile.h> -#include <ipxe/base16.h> -#include <ipxe/smbios.h> -#include "smsc95xx.h" - -/** @file - * - * SMSC LAN95xx USB Ethernet driver - * - */ - -/** Interrupt completion profiler */ -static struct profiler smsc95xx_intr_profiler __profiler = - { .name = "smsc95xx.intr" }; - -/** Bulk IN completion profiler */ -static struct profiler smsc95xx_in_profiler __profiler = - { .name = "smsc95xx.in" }; - -/** Bulk OUT profiler */ -static struct profiler smsc95xx_out_profiler __profiler = - { .name = "smsc95xx.out" }; - -/****************************************************************************** - * - * Register access - * - ****************************************************************************** - */ - -/** - * Write register (without byte-swapping) - * - * @v smsc95xx SMSC95xx device - * @v address Register address - * @v value Register value - * @ret rc Return status code - */ -static int smsc95xx_raw_writel ( struct smsc95xx_device *smsc95xx, - unsigned int address, uint32_t value ) { - int rc; - - /* Write register */ - DBGCIO ( smsc95xx, "SMSC95XX %p [%03x] <= %08x\n", - smsc95xx, address, le32_to_cpu ( value ) ); - if ( ( rc = usb_control ( smsc95xx->usb, SMSC95XX_REGISTER_WRITE, 0, - address, &value, sizeof ( value ) ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not write %03x: %s\n", - smsc95xx, address, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Write register - * - * @v smsc95xx SMSC95xx device - * @v address Register address - * @v value Register value - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -smsc95xx_writel ( struct smsc95xx_device *smsc95xx, unsigned int address, - uint32_t value ) { - int rc; - - /* Write register */ - if ( ( rc = smsc95xx_raw_writel ( smsc95xx, address, - cpu_to_le32 ( value ) ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Read register (without byte-swapping) - * - * @v smsc95xx SMSC95xx device - * @v address Register address - * @ret value Register value - * @ret rc Return status code - */ -static int smsc95xx_raw_readl ( struct smsc95xx_device *smsc95xx, - unsigned int address, uint32_t *value ) { - int rc; - - /* Read register */ - if ( ( rc = usb_control ( smsc95xx->usb, SMSC95XX_REGISTER_READ, 0, - address, value, sizeof ( *value ) ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not read %03x: %s\n", - smsc95xx, address, strerror ( rc ) ); - return rc; - } - DBGCIO ( smsc95xx, "SMSC95XX %p [%03x] => %08x\n", - smsc95xx, address, le32_to_cpu ( *value ) ); - - return 0; -} - -/** - * Read register - * - * @v smsc95xx SMSC95xx device - * @v address Register address - * @ret value Register value - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -smsc95xx_readl ( struct smsc95xx_device *smsc95xx, unsigned int address, - uint32_t *value ) { - int rc; - - /* Read register */ - if ( ( rc = smsc95xx_raw_readl ( smsc95xx, address, value ) ) != 0 ) - return rc; - le32_to_cpus ( value ); - - return 0; -} - -/****************************************************************************** - * - * EEPROM access - * - ****************************************************************************** - */ - -/** - * Wait for EEPROM to become idle - * - * @v smsc95xx SMSC95xx device - * @ret rc Return status code - */ -static int smsc95xx_eeprom_wait ( struct smsc95xx_device *smsc95xx ) { - uint32_t e2p_cmd; - unsigned int i; - int rc; - - /* Wait for EPC_BSY to become clear */ - for ( i = 0 ; i < SMSC95XX_EEPROM_MAX_WAIT_MS ; i++ ) { - - /* Read E2P_CMD and check EPC_BSY */ - if ( ( rc = smsc95xx_readl ( smsc95xx, SMSC95XX_E2P_CMD, - &e2p_cmd ) ) != 0 ) - return rc; - if ( ! ( e2p_cmd & SMSC95XX_E2P_CMD_EPC_BSY ) ) - return 0; - - /* Delay */ - mdelay ( 1 ); - } - - DBGC ( smsc95xx, "SMSC95XX %p timed out waiting for EEPROM\n", - smsc95xx ); - return -ETIMEDOUT; -} - -/** - * Read byte from EEPROM - * - * @v smsc95xx SMSC95xx device - * @v address EEPROM address - * @ret byte Byte read, or negative error - */ -static int smsc95xx_eeprom_read_byte ( struct smsc95xx_device *smsc95xx, - unsigned int address ) { - uint32_t e2p_cmd; - uint32_t e2p_data; - int rc; - - /* Wait for EEPROM to become idle */ - if ( ( rc = smsc95xx_eeprom_wait ( smsc95xx ) ) != 0 ) - return rc; - - /* Initiate read command */ - e2p_cmd = ( SMSC95XX_E2P_CMD_EPC_BSY | SMSC95XX_E2P_CMD_EPC_CMD_READ | - SMSC95XX_E2P_CMD_EPC_ADDR ( address ) ); - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_E2P_CMD, - e2p_cmd ) ) != 0 ) - return rc; - - /* Wait for command to complete */ - if ( ( rc = smsc95xx_eeprom_wait ( smsc95xx ) ) != 0 ) - return rc; - - /* Read EEPROM data */ - if ( ( rc = smsc95xx_readl ( smsc95xx, SMSC95XX_E2P_DATA, - &e2p_data ) ) != 0 ) - return rc; - - return SMSC95XX_E2P_DATA_GET ( e2p_data ); -} - -/** - * Read data from EEPROM - * - * @v smsc95xx SMSC95xx device - * @v address EEPROM address - * @v data Data buffer - * @v len Length of data - * @ret rc Return status code - */ -static int smsc95xx_eeprom_read ( struct smsc95xx_device *smsc95xx, - unsigned int address, void *data, - size_t len ) { - uint8_t *bytes; - int byte; - - /* Read bytes */ - for ( bytes = data ; len-- ; address++, bytes++ ) { - byte = smsc95xx_eeprom_read_byte ( smsc95xx, address ); - if ( byte < 0 ) - return byte; - *bytes = byte; - } - - return 0; -} - -/****************************************************************************** - * - * MAC address - * - ****************************************************************************** - */ - -/** - * Fetch MAC address from EEPROM - * - * @v smsc95xx SMSC95xx device - * @v hw_addr Hardware address to fill in - * @ret rc Return status code - */ -static int smsc95xx_fetch_mac_eeprom ( struct smsc95xx_device *smsc95xx, - uint8_t *hw_addr ) { - int rc; - - /* Read MAC address from EEPROM */ - if ( ( rc = smsc95xx_eeprom_read ( smsc95xx, SMSC95XX_EEPROM_MAC, - hw_addr, ETH_ALEN ) ) != 0 ) - return rc; - - /* Check that EEPROM is physically present */ - if ( ! is_valid_ether_addr ( hw_addr ) ) { - DBGC ( smsc95xx, "SMSC95XX %p has no EEPROM (%s)\n", - smsc95xx, eth_ntoa ( hw_addr ) ); - return -ENODEV; - } - - DBGC ( smsc95xx, "SMSC95XX %p using EEPROM MAC %s\n", - smsc95xx, eth_ntoa ( hw_addr ) ); - return 0; -} - -/** - * Construct MAC address for Honeywell VM3 - * - * @v smsc95xx SMSC95xx device - * @v hw_addr Hardware address to fill in - * @ret rc Return status code - */ -static int smsc95xx_fetch_mac_vm3 ( struct smsc95xx_device *smsc95xx, - uint8_t *hw_addr ) { - struct smbios_structure structure; - struct smbios_system_information system; - struct { - char manufacturer[ 10 /* "Honeywell" + NUL */ ]; - char product[ 4 /* "VM3" + NUL */ ]; - char mac[ base16_encoded_len ( ETH_ALEN ) + 1 /* NUL */ ]; - } strings; - int len; - int rc; - - /* Find system information */ - if ( ( rc = find_smbios_structure ( SMBIOS_TYPE_SYSTEM_INFORMATION, 0, - &structure ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not find system " - "information: %s\n", smsc95xx, strerror ( rc ) ); - return rc; - } - - /* Read system information */ - if ( ( rc = read_smbios_structure ( &structure, &system, - sizeof ( system ) ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not read system " - "information: %s\n", smsc95xx, strerror ( rc ) ); - return rc; - } - - /* NUL-terminate all strings to be fetched */ - memset ( &strings, 0, sizeof ( strings ) ); - - /* Fetch system manufacturer name */ - len = read_smbios_string ( &structure, system.manufacturer, - strings.manufacturer, - ( sizeof ( strings.manufacturer ) - 1 ) ); - if ( len < 0 ) { - rc = len; - DBGC ( smsc95xx, "SMSC95XX %p could not read manufacturer " - "name: %s\n", smsc95xx, strerror ( rc ) ); - return rc; - } - - /* Fetch system product name */ - len = read_smbios_string ( &structure, system.product, strings.product, - ( sizeof ( strings.product ) - 1 ) ); - if ( len < 0 ) { - rc = len; - DBGC ( smsc95xx, "SMSC95XX %p could not read product name: " - "%s\n", smsc95xx, strerror ( rc ) ); - return rc; - } - - /* Ignore non-VM3 devices */ - if ( ( strcmp ( strings.manufacturer, "Honeywell" ) != 0 ) || - ( strcmp ( strings.product, "VM3" ) != 0 ) ) - return -ENOTTY; - - /* Find OEM strings */ - if ( ( rc = find_smbios_structure ( SMBIOS_TYPE_OEM_STRINGS, 0, - &structure ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not find OEM strings: %s\n", - smsc95xx, strerror ( rc ) ); - return rc; - } - - /* Fetch MAC address */ - len = read_smbios_string ( &structure, SMSC95XX_VM3_OEM_STRING_MAC, - strings.mac, ( sizeof ( strings.mac ) - 1 )); - if ( len < 0 ) { - rc = len; - DBGC ( smsc95xx, "SMSC95XX %p could not read OEM string: %s\n", - smsc95xx, strerror ( rc ) ); - return rc; - } - - /* Sanity check */ - if ( len != ( ( int ) ( sizeof ( strings.mac ) - 1 ) ) ) { - DBGC ( smsc95xx, "SMSC95XX %p invalid MAC address \"%s\"\n", - smsc95xx, strings.mac ); - return -EINVAL; - } - - /* Decode MAC address */ - len = base16_decode ( strings.mac, hw_addr, ETH_ALEN ); - if ( len < 0 ) { - rc = len; - DBGC ( smsc95xx, "SMSC95XX %p invalid MAC address \"%s\"\n", - smsc95xx, strings.mac ); - return rc; - } - - DBGC ( smsc95xx, "SMSC95XX %p using VM3 MAC %s\n", - smsc95xx, eth_ntoa ( hw_addr ) ); - return 0; -} - -/** - * Fetch MAC address - * - * @v smsc95xx SMSC95xx device - * @v hw_addr Hardware address to fill in - * @ret rc Return status code - */ -static int smsc95xx_fetch_mac ( struct smsc95xx_device *smsc95xx, - uint8_t *hw_addr ) { - int rc; - - /* Read MAC address from EEPROM, if present */ - if ( ( rc = smsc95xx_fetch_mac_eeprom ( smsc95xx, hw_addr ) ) == 0 ) - return 0; - - /* Construct MAC address for Honeywell VM3, if applicable */ - if ( ( rc = smsc95xx_fetch_mac_vm3 ( smsc95xx, hw_addr ) ) == 0 ) - return 0; - - /* Otherwise, generate a random MAC address */ - eth_random_addr ( hw_addr ); - DBGC ( smsc95xx, "SMSC95XX %p using random MAC %s\n", - smsc95xx, eth_ntoa ( hw_addr ) ); - return 0; -} - -/****************************************************************************** - * - * MII access - * - ****************************************************************************** - */ - -/** - * Wait for MII to become idle - * - * @v smsc95xx SMSC95xx device - * @ret rc Return status code - */ -static int smsc95xx_mii_wait ( struct smsc95xx_device *smsc95xx ) { - uint32_t mii_access; - unsigned int i; - int rc; - - /* Wait for MIIBZY to become clear */ - for ( i = 0 ; i < SMSC95XX_MII_MAX_WAIT_MS ; i++ ) { - - /* Read MII_ACCESS and check MIIBZY */ - if ( ( rc = smsc95xx_readl ( smsc95xx, SMSC95XX_MII_ACCESS, - &mii_access ) ) != 0 ) - return rc; - if ( ! ( mii_access & SMSC95XX_MII_ACCESS_MIIBZY ) ) - return 0; - - /* Delay */ - mdelay ( 1 ); - } - - DBGC ( smsc95xx, "SMSC95XX %p timed out waiting for MII\n", - smsc95xx ); - return -ETIMEDOUT; -} - -/** - * Read from MII register - * - * @v mii MII interface - * @v reg Register address - * @ret value Data read, or negative error - */ -static int smsc95xx_mii_read ( struct mii_interface *mii, unsigned int reg ) { - struct smsc95xx_device *smsc95xx = - container_of ( mii, struct smsc95xx_device, mii ); - uint32_t mii_access; - uint32_t mii_data; - int rc; - - /* Wait for MII to become idle */ - if ( ( rc = smsc95xx_mii_wait ( smsc95xx ) ) != 0 ) - return rc; - - /* Initiate read command */ - mii_access = ( SMSC95XX_MII_ACCESS_PHY_ADDRESS | - SMSC95XX_MII_ACCESS_MIIRINDA ( reg ) | - SMSC95XX_MII_ACCESS_MIIBZY ); - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_MII_ACCESS, - mii_access ) ) != 0 ) - return rc; - - /* Wait for command to complete */ - if ( ( rc = smsc95xx_mii_wait ( smsc95xx ) ) != 0 ) - return rc; - - /* Read MII data */ - if ( ( rc = smsc95xx_readl ( smsc95xx, SMSC95XX_MII_DATA, - &mii_data ) ) != 0 ) - return rc; - - return SMSC95XX_MII_DATA_GET ( mii_data ); -} - -/** - * Write to MII register - * - * @v mii MII interface - * @v reg Register address - * @v data Data to write - * @ret rc Return status code - */ -static int smsc95xx_mii_write ( struct mii_interface *mii, unsigned int reg, - unsigned int data ) { - struct smsc95xx_device *smsc95xx = - container_of ( mii, struct smsc95xx_device, mii ); - uint32_t mii_access; - uint32_t mii_data; - int rc; - - /* Wait for MII to become idle */ - if ( ( rc = smsc95xx_mii_wait ( smsc95xx ) ) != 0 ) - return rc; - - /* Write MII data */ - mii_data = SMSC95XX_MII_DATA_SET ( data ); - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_MII_DATA, - mii_data ) ) != 0 ) - return rc; - - /* Initiate write command */ - mii_access = ( SMSC95XX_MII_ACCESS_PHY_ADDRESS | - SMSC95XX_MII_ACCESS_MIIRINDA ( reg ) | - SMSC95XX_MII_ACCESS_MIIWNR | - SMSC95XX_MII_ACCESS_MIIBZY ); - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_MII_ACCESS, - mii_access ) ) != 0 ) - return rc; - - /* Wait for command to complete */ - if ( ( rc = smsc95xx_mii_wait ( smsc95xx ) ) != 0 ) - return rc; - - return 0; -} - -/** MII operations */ -static struct mii_operations smsc95xx_mii_operations = { - .read = smsc95xx_mii_read, - .write = smsc95xx_mii_write, -}; - -/** - * Check link status - * - * @v smsc95xx SMSC95xx device - * @ret rc Return status code - */ -static int smsc95xx_check_link ( struct smsc95xx_device *smsc95xx ) { - struct net_device *netdev = smsc95xx->netdev; - int intr; - int rc; - - /* Read PHY interrupt source */ - intr = mii_read ( &smsc95xx->mii, SMSC95XX_MII_PHY_INTR_SOURCE ); - if ( intr < 0 ) { - rc = intr; - DBGC ( smsc95xx, "SMSC95XX %p could not get PHY interrupt " - "source: %s\n", smsc95xx, strerror ( rc ) ); - return rc; - } - - /* Acknowledge PHY interrupt */ - if ( ( rc = mii_write ( &smsc95xx->mii, SMSC95XX_MII_PHY_INTR_SOURCE, - intr ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not acknowledge PHY " - "interrupt: %s\n", smsc95xx, strerror ( rc ) ); - return rc; - } - - /* Check link status */ - if ( ( rc = mii_check_link ( &smsc95xx->mii, netdev ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not check link: %s\n", - smsc95xx, strerror ( rc ) ); - return rc; - } - - DBGC ( smsc95xx, "SMSC95XX %p link %s (intr %#04x)\n", - smsc95xx, ( netdev_link_ok ( netdev ) ? "up" : "down" ), intr ); - return 0; -} - -/****************************************************************************** - * - * Statistics (for debugging) - * - ****************************************************************************** - */ - -/** - * Get RX statistics - * - * @v smsc95xx SMSC95xx device - * @v stats Statistics to fill in - * @ret rc Return status code - */ -static int smsc95xx_get_rx_statistics ( struct smsc95xx_device *smsc95xx, - struct smsc95xx_rx_statistics *stats ) { - int rc; - - /* Get statistics */ - if ( ( rc = usb_control ( smsc95xx->usb, SMSC95XX_GET_STATISTICS, 0, - SMSC95XX_RX_STATISTICS, stats, - sizeof ( *stats ) ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not get RX statistics: " - "%s\n", smsc95xx, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Get TX statistics - * - * @v smsc95xx SMSC95xx device - * @v stats Statistics to fill in - * @ret rc Return status code - */ -static int smsc95xx_get_tx_statistics ( struct smsc95xx_device *smsc95xx, - struct smsc95xx_tx_statistics *stats ) { - int rc; - - /* Get statistics */ - if ( ( rc = usb_control ( smsc95xx->usb, SMSC95XX_GET_STATISTICS, 0, - SMSC95XX_TX_STATISTICS, stats, - sizeof ( *stats ) ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not get TX statistics: " - "%s\n", smsc95xx, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/** - * Dump statistics (for debugging) - * - * @v smsc95xx SMSC95xx device - * @ret rc Return status code - */ -static int smsc95xx_dump_statistics ( struct smsc95xx_device *smsc95xx ) { - struct smsc95xx_rx_statistics rx; - struct smsc95xx_tx_statistics tx; - int rc; - - /* Do nothing unless debugging is enabled */ - if ( ! DBG_LOG ) - return 0; - - /* Get RX statistics */ - if ( ( rc = smsc95xx_get_rx_statistics ( smsc95xx, &rx ) ) != 0 ) - return rc; - - /* Get TX statistics */ - if ( ( rc = smsc95xx_get_tx_statistics ( smsc95xx, &tx ) ) != 0 ) - return rc; - - /* Dump statistics */ - DBGC ( smsc95xx, "SMSC95XX %p RX good %d bad %d crc %d und %d aln %d " - "ovr %d lat %d drp %d\n", smsc95xx, le32_to_cpu ( rx.good ), - le32_to_cpu ( rx.bad ), le32_to_cpu ( rx.crc ), - le32_to_cpu ( rx.undersize ), le32_to_cpu ( rx.alignment ), - le32_to_cpu ( rx.oversize ), le32_to_cpu ( rx.late ), - le32_to_cpu ( rx.dropped ) ); - DBGC ( smsc95xx, "SMSC95XX %p TX good %d bad %d pau %d sgl %d mul %d " - "exc %d lat %d und %d def %d car %d\n", smsc95xx, - le32_to_cpu ( tx.good ), le32_to_cpu ( tx.bad ), - le32_to_cpu ( tx.pause ), le32_to_cpu ( tx.single ), - le32_to_cpu ( tx.multiple ), le32_to_cpu ( tx.excessive ), - le32_to_cpu ( tx.late ), le32_to_cpu ( tx.underrun ), - le32_to_cpu ( tx.deferred ), le32_to_cpu ( tx.carrier ) ); - - return 0; -} - -/****************************************************************************** - * - * Device reset - * - ****************************************************************************** - */ - -/** - * Reset device - * - * @v smsc95xx SMSC95xx device - * @ret rc Return status code - */ -static int smsc95xx_reset ( struct smsc95xx_device *smsc95xx ) { - uint32_t hw_cfg; - uint32_t led_gpio_cfg; - int rc; - - /* Reset device */ - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_HW_CFG, - SMSC95XX_HW_CFG_LRST ) ) != 0 ) - return rc; - - /* Wait for reset to complete */ - udelay ( SMSC95XX_RESET_DELAY_US ); - - /* Check that reset has completed */ - if ( ( rc = smsc95xx_readl ( smsc95xx, SMSC95XX_HW_CFG, - &hw_cfg ) ) != 0 ) - return rc; - if ( hw_cfg & SMSC95XX_HW_CFG_LRST ) { - DBGC ( smsc95xx, "SMSC95XX %p failed to reset\n", smsc95xx ); - return -ETIMEDOUT; - } - - /* Configure LEDs */ - led_gpio_cfg = ( SMSC95XX_LED_GPIO_CFG_GPCTL2_NSPD_LED | - SMSC95XX_LED_GPIO_CFG_GPCTL1_NLNKA_LED | - SMSC95XX_LED_GPIO_CFG_GPCTL0_NFDX_LED ); - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_LED_GPIO_CFG, - led_gpio_cfg ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not configure LEDs: %s\n", - smsc95xx, strerror ( rc ) ); - /* Ignore error and continue */ - } - - return 0; -} - -/****************************************************************************** - * - * Endpoint operations - * - ****************************************************************************** - */ - -/** - * Complete interrupt transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void smsc95xx_intr_complete ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int rc ) { - struct smsc95xx_device *smsc95xx = - container_of ( ep, struct smsc95xx_device, usbnet.intr ); - struct net_device *netdev = smsc95xx->netdev; - struct smsc95xx_interrupt *intr; - - /* Profile completions */ - profile_start ( &smsc95xx_intr_profiler ); - - /* Ignore packets cancelled when the endpoint closes */ - if ( ! ep->open ) - goto done; - - /* Record USB errors against the network device */ - if ( rc != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p interrupt failed: %s\n", - smsc95xx, strerror ( rc ) ); - DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) ); - netdev_rx_err ( netdev, NULL, rc ); - goto done; - } - - /* Extract interrupt data */ - if ( iob_len ( iobuf ) != sizeof ( *intr ) ) { - DBGC ( smsc95xx, "SMSC95XX %p malformed interrupt\n", - smsc95xx ); - DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) ); - netdev_rx_err ( netdev, NULL, rc ); - goto done; - } - intr = iobuf->data; - - /* Record interrupt status */ - smsc95xx->int_sts = le32_to_cpu ( intr->int_sts ); - profile_stop ( &smsc95xx_intr_profiler ); - - done: - /* Free I/O buffer */ - free_iob ( iobuf ); -} - -/** Interrupt endpoint operations */ -static struct usb_endpoint_driver_operations smsc95xx_intr_operations = { - .complete = smsc95xx_intr_complete, -}; - -/** - * Complete bulk IN transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void smsc95xx_in_complete ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int rc ) { - struct smsc95xx_device *smsc95xx = - container_of ( ep, struct smsc95xx_device, usbnet.in ); - struct net_device *netdev = smsc95xx->netdev; - struct smsc95xx_rx_header *header; - - /* Profile completions */ - profile_start ( &smsc95xx_in_profiler ); - - /* Ignore packets cancelled when the endpoint closes */ - if ( ! ep->open ) { - free_iob ( iobuf ); - return; - } - - /* Record USB errors against the network device */ - if ( rc != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p bulk IN failed: %s\n", - smsc95xx, strerror ( rc ) ); - goto err; - } - - /* Sanity check */ - if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) { - DBGC ( smsc95xx, "SMSC95XX %p underlength bulk IN\n", - smsc95xx ); - DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) ); - rc = -EINVAL; - goto err; - } - - /* Strip header and CRC */ - header = iobuf->data; - iob_pull ( iobuf, sizeof ( *header ) ); - iob_unput ( iobuf, 4 /* CRC */ ); - - /* Check for errors */ - if ( header->command & cpu_to_le32 ( SMSC95XX_RX_RUNT | - SMSC95XX_RX_LATE | - SMSC95XX_RX_CRC ) ) { - DBGC ( smsc95xx, "SMSC95XX %p receive error (%08x):\n", - smsc95xx, le32_to_cpu ( header->command ) ); - DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) ); - rc = -EIO; - goto err; - } - - /* Hand off to network stack */ - netdev_rx ( netdev, iob_disown ( iobuf ) ); - - profile_stop ( &smsc95xx_in_profiler ); - return; - - err: - /* Hand off to network stack */ - netdev_rx_err ( netdev, iob_disown ( iobuf ), rc ); -} - -/** Bulk IN endpoint operations */ -static struct usb_endpoint_driver_operations smsc95xx_in_operations = { - .complete = smsc95xx_in_complete, -}; - -/** - * Transmit packet - * - * @v smsc95xx SMSC95xx device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int smsc95xx_out_transmit ( struct smsc95xx_device *smsc95xx, - struct io_buffer *iobuf ) { - struct smsc95xx_tx_header *header; - size_t len = iob_len ( iobuf ); - int rc; - - /* Profile transmissions */ - profile_start ( &smsc95xx_out_profiler ); - - /* Prepend header */ - if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *header ) ) ) != 0 ) - return rc; - header = iob_push ( iobuf, sizeof ( *header ) ); - header->command = cpu_to_le32 ( SMSC95XX_TX_FIRST | SMSC95XX_TX_LAST | - SMSC95XX_TX_LEN ( len ) ); - header->len = cpu_to_le32 ( len ); - - /* Enqueue I/O buffer */ - if ( ( rc = usb_stream ( &smsc95xx->usbnet.out, iobuf, 0 ) ) != 0 ) - return rc; - - profile_stop ( &smsc95xx_out_profiler ); - return 0; -} - -/** - * Complete bulk OUT transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v rc Completion status code - */ -static void smsc95xx_out_complete ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int rc ) { - struct smsc95xx_device *smsc95xx = - container_of ( ep, struct smsc95xx_device, usbnet.out ); - struct net_device *netdev = smsc95xx->netdev; - - /* Report TX completion */ - netdev_tx_complete_err ( netdev, iobuf, rc ); -} - -/** Bulk OUT endpoint operations */ -static struct usb_endpoint_driver_operations smsc95xx_out_operations = { - .complete = smsc95xx_out_complete, -}; - -/****************************************************************************** - * - * Network device interface - * - ****************************************************************************** - */ - -/** - * Open network device - * - * @v netdev Network device - * @ret rc Return status code - */ -static int smsc95xx_open ( struct net_device *netdev ) { - struct smsc95xx_device *smsc95xx = netdev->priv; - union smsc95xx_mac mac; - int rc; - - /* Clear stored interrupt status */ - smsc95xx->int_sts = 0; - - /* Copy MAC address */ - memset ( &mac, 0, sizeof ( mac ) ); - memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN ); - - /* Configure bulk IN empty response */ - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_HW_CFG, - SMSC95XX_HW_CFG_BIR ) ) != 0 ) - goto err_hw_cfg; - - /* Open USB network device */ - if ( ( rc = usbnet_open ( &smsc95xx->usbnet ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not open: %s\n", - smsc95xx, strerror ( rc ) ); - goto err_open; - } - - /* Configure interrupt endpoint */ - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_INT_EP_CTL, - ( SMSC95XX_INT_EP_CTL_RXDF_EN | - SMSC95XX_INT_EP_CTL_PHY_EN ) ) ) != 0 ) - goto err_int_ep_ctl; - - /* Configure bulk IN delay */ - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_BULK_IN_DLY, - SMSC95XX_BULK_IN_DLY_SET ( 0 ) ) ) != 0 ) - goto err_bulk_in_dly; - - /* Configure MAC */ - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_MAC_CR, - ( SMSC95XX_MAC_CR_RXALL | - SMSC95XX_MAC_CR_FDPX | - SMSC95XX_MAC_CR_MCPAS | - SMSC95XX_MAC_CR_PRMS | - SMSC95XX_MAC_CR_PASSBAD | - SMSC95XX_MAC_CR_TXEN | - SMSC95XX_MAC_CR_RXEN ) ) ) != 0 ) - goto err_mac_cr; - - /* Configure transmit datapath */ - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_TX_CFG, - SMSC95XX_TX_CFG_ON ) ) != 0 ) - goto err_tx_cfg; - - /* Write MAC address high register */ - if ( ( rc = smsc95xx_raw_writel ( smsc95xx, SMSC95XX_ADDRH, - mac.addr.h ) ) != 0 ) - goto err_addrh; - - /* Write MAC address low register */ - if ( ( rc = smsc95xx_raw_writel ( smsc95xx, SMSC95XX_ADDRL, - mac.addr.l ) ) != 0 ) - goto err_addrl; - - /* Enable PHY interrupts */ - if ( ( rc = mii_write ( &smsc95xx->mii, SMSC95XX_MII_PHY_INTR_MASK, - ( SMSC95XX_PHY_INTR_ANEG_DONE | - SMSC95XX_PHY_INTR_LINK_DOWN ) ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not set PHY interrupt " - "mask: %s\n", smsc95xx, strerror ( rc ) ); - goto err_phy_intr_mask; - } - - /* Update link status */ - smsc95xx_check_link ( smsc95xx ); - - return 0; - - err_phy_intr_mask: - err_addrl: - err_addrh: - err_tx_cfg: - err_mac_cr: - err_bulk_in_dly: - err_int_ep_ctl: - usbnet_close ( &smsc95xx->usbnet ); - err_open: - err_hw_cfg: - smsc95xx_reset ( smsc95xx ); - return rc; -} - -/** - * Close network device - * - * @v netdev Network device - */ -static void smsc95xx_close ( struct net_device *netdev ) { - struct smsc95xx_device *smsc95xx = netdev->priv; - - /* Close USB network device */ - usbnet_close ( &smsc95xx->usbnet ); - - /* Dump statistics (for debugging) */ - smsc95xx_dump_statistics ( smsc95xx ); - - /* Reset device */ - smsc95xx_reset ( smsc95xx ); -} - -/** - * Transmit packet - * - * @v netdev Network device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int smsc95xx_transmit ( struct net_device *netdev, - struct io_buffer *iobuf ) { - struct smsc95xx_device *smsc95xx = netdev->priv; - int rc; - - /* Transmit packet */ - if ( ( rc = smsc95xx_out_transmit ( smsc95xx, iobuf ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Poll for completed and received packets - * - * @v netdev Network device - */ -static void smsc95xx_poll ( struct net_device *netdev ) { - struct smsc95xx_device *smsc95xx = netdev->priv; - uint32_t int_sts; - int rc; - - /* Poll USB bus */ - usb_poll ( smsc95xx->bus ); - - /* Refill endpoints */ - if ( ( rc = usbnet_refill ( &smsc95xx->usbnet ) ) != 0 ) - netdev_rx_err ( netdev, NULL, rc ); - - /* Do nothing more unless there are interrupts to handle */ - int_sts = smsc95xx->int_sts; - if ( ! int_sts ) - return; - - /* Check link status if applicable */ - if ( int_sts & SMSC95XX_INT_STS_PHY_INT ) { - smsc95xx_check_link ( smsc95xx ); - int_sts &= ~SMSC95XX_INT_STS_PHY_INT; - } - - /* Record RX FIFO overflow if applicable */ - if ( int_sts & SMSC95XX_INT_STS_RXDF_INT ) { - DBGC2 ( smsc95xx, "SMSC95XX %p RX FIFO overflowed\n", - smsc95xx ); - netdev_rx_err ( netdev, NULL, -ENOBUFS ); - int_sts &= ~SMSC95XX_INT_STS_RXDF_INT; - } - - /* Check for unexpected interrupts */ - if ( int_sts ) { - DBGC ( smsc95xx, "SMSC95XX %p unexpected interrupt %#08x\n", - smsc95xx, int_sts ); - netdev_rx_err ( netdev, NULL, -ENOTTY ); - } - - /* Clear interrupts */ - if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_INT_STS, - smsc95xx->int_sts ) ) != 0 ) - netdev_rx_err ( netdev, NULL, rc ); - smsc95xx->int_sts = 0; -} - -/** SMSC95xx network device operations */ -static struct net_device_operations smsc95xx_operations = { - .open = smsc95xx_open, - .close = smsc95xx_close, - .transmit = smsc95xx_transmit, - .poll = smsc95xx_poll, -}; - -/****************************************************************************** - * - * USB interface - * - ****************************************************************************** - */ - -/** - * Probe device - * - * @v func USB function - * @v config Configuration descriptor - * @ret rc Return status code - */ -static int smsc95xx_probe ( struct usb_function *func, - struct usb_configuration_descriptor *config ) { - struct usb_device *usb = func->usb; - struct net_device *netdev; - struct smsc95xx_device *smsc95xx; - int rc; - - /* Allocate and initialise structure */ - netdev = alloc_etherdev ( sizeof ( *smsc95xx ) ); - if ( ! netdev ) { - rc = -ENOMEM; - goto err_alloc; - } - netdev_init ( netdev, &smsc95xx_operations ); - netdev->dev = &func->dev; - smsc95xx = netdev->priv; - memset ( smsc95xx, 0, sizeof ( *smsc95xx ) ); - smsc95xx->usb = usb; - smsc95xx->bus = usb->port->hub->bus; - smsc95xx->netdev = netdev; - usbnet_init ( &smsc95xx->usbnet, func, &smsc95xx_intr_operations, - &smsc95xx_in_operations, &smsc95xx_out_operations ); - usb_refill_init ( &smsc95xx->usbnet.intr, 0, 0, - SMSC95XX_INTR_MAX_FILL ); - usb_refill_init ( &smsc95xx->usbnet.in, - ( sizeof ( struct smsc95xx_tx_header ) - - sizeof ( struct smsc95xx_rx_header ) ), - SMSC95XX_IN_MTU, SMSC95XX_IN_MAX_FILL ); - mii_init ( &smsc95xx->mii, &smsc95xx_mii_operations ); - DBGC ( smsc95xx, "SMSC95XX %p on %s\n", smsc95xx, func->name ); - - /* Describe USB network device */ - if ( ( rc = usbnet_describe ( &smsc95xx->usbnet, config ) ) != 0 ) { - DBGC ( smsc95xx, "SMSC95XX %p could not describe: %s\n", - smsc95xx, strerror ( rc ) ); - goto err_describe; - } - - /* Reset device */ - if ( ( rc = smsc95xx_reset ( smsc95xx ) ) != 0 ) - goto err_reset; - - /* Read MAC address */ - if ( ( rc = smsc95xx_fetch_mac ( smsc95xx, netdev->hw_addr ) ) != 0 ) - goto err_fetch_mac; - - /* Register network device */ - if ( ( rc = register_netdev ( netdev ) ) != 0 ) - goto err_register; - - usb_func_set_drvdata ( func, netdev ); - return 0; - - unregister_netdev ( netdev ); - err_register: - err_fetch_mac: - err_reset: - err_describe: - netdev_nullify ( netdev ); - netdev_put ( netdev ); - err_alloc: - return rc; -} - -/** - * Remove device - * - * @v func USB function - */ -static void smsc95xx_remove ( struct usb_function *func ) { - struct net_device *netdev = usb_func_get_drvdata ( func ); - - unregister_netdev ( netdev ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} - -/** SMSC95xx device IDs */ -static struct usb_device_id smsc95xx_ids[] = { - { - .name = "smsc9500", - .vendor = 0x0424, - .product = 0x9500, - }, - { - .name = "smsc9505", - .vendor = 0x0424, - .product = 0x9505, - }, - { - .name = "smsc9500a", - .vendor = 0x0424, - .product = 0x9e00, - }, - { - .name = "smsc9505a", - .vendor = 0x0424, - .product = 0x9e01, - }, - { - .name = "smsc9514", - .vendor = 0x0424, - .product = 0xec00, - }, - { - .name = "smsc9500-s", - .vendor = 0x0424, - .product = 0x9900, - }, - { - .name = "smsc9505-s", - .vendor = 0x0424, - .product = 0x9901, - }, - { - .name = "smsc9500a-s", - .vendor = 0x0424, - .product = 0x9902, - }, - { - .name = "smsc9505a-s", - .vendor = 0x0424, - .product = 0x9903, - }, - { - .name = "smsc9514-s", - .vendor = 0x0424, - .product = 0x9904, - }, - { - .name = "smsc9500a-h", - .vendor = 0x0424, - .product = 0x9905, - }, - { - .name = "smsc9505a-h", - .vendor = 0x0424, - .product = 0x9906, - }, - { - .name = "smsc9500-2", - .vendor = 0x0424, - .product = 0x9907, - }, - { - .name = "smsc9500a-2", - .vendor = 0x0424, - .product = 0x9908, - }, - { - .name = "smsc9514-2", - .vendor = 0x0424, - .product = 0x9909, - }, - { - .name = "smsc9530", - .vendor = 0x0424, - .product = 0x9530, - }, - { - .name = "smsc9730", - .vendor = 0x0424, - .product = 0x9730, - }, - { - .name = "smsc89530", - .vendor = 0x0424, - .product = 0x9e08, - }, -}; - -/** SMSC LAN95xx driver */ -struct usb_driver smsc95xx_driver __usb_driver = { - .ids = smsc95xx_ids, - .id_count = ( sizeof ( smsc95xx_ids ) / sizeof ( smsc95xx_ids[0] ) ), - .class = USB_CLASS_ID ( 0xff, 0x00, 0xff ), - .score = USB_SCORE_NORMAL, - .probe = smsc95xx_probe, - .remove = smsc95xx_remove, -}; diff --git a/roms/ipxe/src/drivers/net/smsc95xx.h b/roms/ipxe/src/drivers/net/smsc95xx.h deleted file mode 100644 index c2512e0ee..000000000 --- a/roms/ipxe/src/drivers/net/smsc95xx.h +++ /dev/null @@ -1,269 +0,0 @@ -#ifndef _SMSC95XX_H -#define _SMSC95XX_H - -/** @file - * - * SMSC LAN95xx USB Ethernet driver - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/usb.h> -#include <ipxe/usbnet.h> -#include <ipxe/if_ether.h> -#include <ipxe/mii.h> - -/** Register write command */ -#define SMSC95XX_REGISTER_WRITE \ - ( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \ - USB_REQUEST_TYPE ( 0xa0 ) ) - -/** Register read command */ -#define SMSC95XX_REGISTER_READ \ - ( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \ - USB_REQUEST_TYPE ( 0xa1 ) ) - -/** Get statistics command */ -#define SMSC95XX_GET_STATISTICS \ - ( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \ - USB_REQUEST_TYPE ( 0xa2 ) ) - -/** Interrupt status register */ -#define SMSC95XX_INT_STS 0x008 -#define SMSC95XX_INT_STS_RXDF_INT 0x00000800UL /**< RX FIFO overflow */ -#define SMSC95XX_INT_STS_PHY_INT 0x00008000UL /**< PHY interrupt */ - -/** Transmit configuration register */ -#define SMSC95XX_TX_CFG 0x010 -#define SMSC95XX_TX_CFG_ON 0x00000004UL /**< TX enable */ - -/** Hardware configuration register */ -#define SMSC95XX_HW_CFG 0x014 -#define SMSC95XX_HW_CFG_BIR 0x00001000UL /**< Bulk IN use NAK */ -#define SMSC95XX_HW_CFG_LRST 0x00000008UL /**< Soft lite reset */ - -/** LED GPIO configuration register */ -#define SMSC95XX_LED_GPIO_CFG 0x024 -#define SMSC95XX_LED_GPIO_CFG_GPCTL2(x) ( (x) << 24 ) /**< GPIO 2 control */ -#define SMSC95XX_LED_GPIO_CFG_GPCTL2_NSPD_LED \ - SMSC95XX_LED_GPIO_CFG_GPCTL2 ( 1 ) /**< Link speed LED */ -#define SMSC95XX_LED_GPIO_CFG_GPCTL1(x) ( (x) << 20 ) /**< GPIO 1 control */ -#define SMSC95XX_LED_GPIO_CFG_GPCTL1_NLNKA_LED \ - SMSC95XX_LED_GPIO_CFG_GPCTL1 ( 1 ) /**< Activity LED */ -#define SMSC95XX_LED_GPIO_CFG_GPCTL0(x) ( (x) << 16 ) /**< GPIO 0 control */ -#define SMSC95XX_LED_GPIO_CFG_GPCTL0_NFDX_LED \ - SMSC95XX_LED_GPIO_CFG_GPCTL0 ( 1 ) /**< Full-duplex LED */ - -/** EEPROM command register */ -#define SMSC95XX_E2P_CMD 0x030 -#define SMSC95XX_E2P_CMD_EPC_BSY 0x80000000UL /**< EPC busy */ -#define SMSC95XX_E2P_CMD_EPC_CMD_READ 0x00000000UL /**< READ command */ -#define SMSC95XX_E2P_CMD_EPC_ADDR(addr) ( (addr) << 0 ) /**< EPC address */ - -/** EEPROM data register */ -#define SMSC95XX_E2P_DATA 0x034 -#define SMSC95XX_E2P_DATA_GET(e2p_data) \ - ( ( (e2p_data) >> 0 ) & 0xff ) /**< EEPROM data */ - -/** MAC address EEPROM address */ -#define SMSC95XX_EEPROM_MAC 0x01 - -/** Interrupt endpoint control register */ -#define SMSC95XX_INT_EP_CTL 0x068 -#define SMSC95XX_INT_EP_CTL_RXDF_EN 0x00000800UL /**< RX FIFO overflow */ -#define SMSC95XX_INT_EP_CTL_PHY_EN 0x00008000UL /**< PHY interrupt */ - -/** Bulk IN delay register */ -#define SMSC95XX_BULK_IN_DLY 0x06c -#define SMSC95XX_BULK_IN_DLY_SET(ticks) ( (ticks) << 0 ) /**< Delay / 16.7ns */ - -/** MAC control register */ -#define SMSC95XX_MAC_CR 0x100 -#define SMSC95XX_MAC_CR_RXALL 0x80000000UL /**< Receive all */ -#define SMSC95XX_MAC_CR_FDPX 0x00100000UL /**< Full duplex */ -#define SMSC95XX_MAC_CR_MCPAS 0x00080000UL /**< All multicast */ -#define SMSC95XX_MAC_CR_PRMS 0x00040000UL /**< Promiscuous */ -#define SMSC95XX_MAC_CR_PASSBAD 0x00010000UL /**< Pass bad frames */ -#define SMSC95XX_MAC_CR_TXEN 0x00000008UL /**< TX enabled */ -#define SMSC95XX_MAC_CR_RXEN 0x00000004UL /**< RX enabled */ - -/** MAC address high register */ -#define SMSC95XX_ADDRH 0x104 - -/** MAC address low register */ -#define SMSC95XX_ADDRL 0x108 - -/** MII access register */ -#define SMSC95XX_MII_ACCESS 0x114 -#define SMSC95XX_MII_ACCESS_PHY_ADDRESS 0x00000800UL /**< PHY address */ -#define SMSC95XX_MII_ACCESS_MIIRINDA(addr) ( (addr) << 6 ) /**< MII register */ -#define SMSC95XX_MII_ACCESS_MIIWNR 0x00000002UL /**< MII write */ -#define SMSC95XX_MII_ACCESS_MIIBZY 0x00000001UL /**< MII busy */ - -/** MII data register */ -#define SMSC95XX_MII_DATA 0x118 -#define SMSC95XX_MII_DATA_SET(data) ( (data) << 0 ) /**< Set data */ -#define SMSC95XX_MII_DATA_GET(mii_data) \ - ( ( (mii_data) >> 0 ) & 0xffff ) /**< Get data */ - -/** PHY interrupt source MII register */ -#define SMSC95XX_MII_PHY_INTR_SOURCE 29 - -/** PHY interrupt mask MII register */ -#define SMSC95XX_MII_PHY_INTR_MASK 30 - -/** PHY interrupt: auto-negotiation complete */ -#define SMSC95XX_PHY_INTR_ANEG_DONE 0x0040 - -/** PHY interrupt: link down */ -#define SMSC95XX_PHY_INTR_LINK_DOWN 0x0010 - -/** MAC address */ -union smsc95xx_mac { - /** MAC receive address registers */ - struct { - /** MAC receive address low register */ - uint32_t l; - /** MAC receive address high register */ - uint32_t h; - } __attribute__ (( packed )) addr; - /** Raw MAC address */ - uint8_t raw[ETH_ALEN]; -}; - -/** Receive packet header */ -struct smsc95xx_rx_header { - /** Command word */ - uint32_t command; -} __attribute__ (( packed )); - -/** Runt frame */ -#define SMSC95XX_RX_RUNT 0x00004000UL - -/** Late collision */ -#define SMSC95XX_RX_LATE 0x00000040UL - -/** CRC error */ -#define SMSC95XX_RX_CRC 0x00000002UL - -/** Transmit packet header */ -struct smsc95xx_tx_header { - /** Command word */ - uint32_t command; - /** Frame length */ - uint32_t len; -} __attribute__ (( packed )); - -/** First segment */ -#define SMSC95XX_TX_FIRST 0x00002000UL - -/** Last segment */ -#define SMSC95XX_TX_LAST 0x00001000UL - -/** Buffer size */ -#define SMSC95XX_TX_LEN(len) ( (len) << 0 ) - -/** Interrupt packet format */ -struct smsc95xx_interrupt { - /** Current value of INT_STS register */ - uint32_t int_sts; -} __attribute__ (( packed )); - -/** Receive statistics */ -struct smsc95xx_rx_statistics { - /** Good frames */ - uint32_t good; - /** CRC errors */ - uint32_t crc; - /** Runt frame errors */ - uint32_t undersize; - /** Alignment errors */ - uint32_t alignment; - /** Frame too long errors */ - uint32_t oversize; - /** Later collision errors */ - uint32_t late; - /** Bad frames */ - uint32_t bad; - /** Dropped frames */ - uint32_t dropped; -} __attribute__ (( packed )); - -/** Receive statistics */ -#define SMSC95XX_RX_STATISTICS 0 - -/** Transmit statistics */ -struct smsc95xx_tx_statistics { - /** Good frames */ - uint32_t good; - /** Pause frames */ - uint32_t pause; - /** Single collisions */ - uint32_t single; - /** Multiple collisions */ - uint32_t multiple; - /** Excessive collisions */ - uint32_t excessive; - /** Late collisions */ - uint32_t late; - /** Buffer underruns */ - uint32_t underrun; - /** Excessive deferrals */ - uint32_t deferred; - /** Carrier errors */ - uint32_t carrier; - /** Bad frames */ - uint32_t bad; -} __attribute__ (( packed )); - -/** Transmit statistics */ -#define SMSC95XX_TX_STATISTICS 1 - -/** A SMSC95xx network device */ -struct smsc95xx_device { - /** USB device */ - struct usb_device *usb; - /** USB bus */ - struct usb_bus *bus; - /** Network device */ - struct net_device *netdev; - /** USB network device */ - struct usbnet_device usbnet; - /** MII interface */ - struct mii_interface mii; - /** Interrupt status */ - uint32_t int_sts; -}; - -/** Reset delay (in microseconds) */ -#define SMSC95XX_RESET_DELAY_US 2 - -/** Maximum time to wait for EEPROM (in milliseconds) */ -#define SMSC95XX_EEPROM_MAX_WAIT_MS 100 - -/** Maximum time to wait for MII (in milliseconds) */ -#define SMSC95XX_MII_MAX_WAIT_MS 100 - -/** Interrupt maximum fill level - * - * This is a policy decision. - */ -#define SMSC95XX_INTR_MAX_FILL 2 - -/** Bulk IN maximum fill level - * - * This is a policy decision. - */ -#define SMSC95XX_IN_MAX_FILL 8 - -/** Bulk IN buffer size */ -#define SMSC95XX_IN_MTU \ - ( sizeof ( struct smsc95xx_rx_header ) + \ - ETH_FRAME_LEN + 4 /* possible VLAN header */ \ - + 4 /* CRC */ ) - -/** Honeywell VM3 MAC address OEM string index */ -#define SMSC95XX_VM3_OEM_STRING_MAC 2 - -#endif /* _SMSC95XX_H */ diff --git a/roms/ipxe/src/drivers/net/tg3/tg3.c b/roms/ipxe/src/drivers/net/tg3/tg3.c index 1bed06649..42bfa2d99 100644 --- a/roms/ipxe/src/drivers/net/tg3/tg3.c +++ b/roms/ipxe/src/drivers/net/tg3/tg3.c @@ -486,8 +486,6 @@ static void tg3_poll(struct net_device *dev) */ tp->hw_status->status &= ~SD_STATUS_UPDATED; - mb(); - tg3_poll_link(tp); tg3_tx_complete(dev); tg3_rx_complete(dev); @@ -547,7 +545,7 @@ static int tg3_test_dma(struct tg3 *tp) goto out_nofree; } buf_dma = virt_to_bus(buf); - DBGC2(tp->dev, "dma test buffer, virt: %p phys: %#016lx\n", buf, buf_dma); + DBGC2(tp->dev, "dma test buffer, virt: %p phys: %#08x\n", buf, buf_dma); if (tg3_flag(tp, 57765_PLUS)) { tp->dma_rwctrl = DMA_RWCTRL_DIS_CACHE_ALIGNMENT; diff --git a/roms/ipxe/src/drivers/net/tg3/tg3.h b/roms/ipxe/src/drivers/net/tg3/tg3.h index be02c5719..2b85b065b 100644 --- a/roms/ipxe/src/drivers/net/tg3/tg3.h +++ b/roms/ipxe/src/drivers/net/tg3/tg3.h @@ -52,6 +52,7 @@ #define PCI_X_CMD 2 /* Modes & Features */ #define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */ +#define PCI_EXP_DEVCTL 8 /* Device Control */ #define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */ #define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */ #define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */ @@ -2788,7 +2789,7 @@ struct tg3_hw_stats { u8 __reserved4[0xb00-0x9c8]; }; -typedef unsigned long dma_addr_t; +typedef u32 dma_addr_t; /* 'mapping' is superfluous as the chip does not write into * the tx/rx post rings so we could just fetch it from there. @@ -3320,25 +3321,43 @@ void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val); /* Functions & macros to verify TG3_FLAGS types */ +static inline int variable_test_bit(int nr, volatile const unsigned long *addr) +{ + int oldbit; + + asm volatile("bt %2,%1\n\t" + "sbb %0,%0" + : "=r" (oldbit) + : "m" (*(unsigned long *)addr), "Ir" (nr)); + + return oldbit; +} + static inline int _tg3_flag(enum TG3_FLAGS flag, unsigned long *bits) { - unsigned int index = ( flag / ( 8 * sizeof ( *bits ) ) ); - unsigned int bit = ( flag % ( 8 * sizeof ( *bits ) ) ); - return ( !! ( bits[index] & ( 1UL << bit ) ) ); + return variable_test_bit(flag, bits); +} + +#define BITOP_ADDR(x) "+m" (*(volatile long *) (x)) + +static inline void __set_bit(int nr, volatile unsigned long *addr) +{ + asm volatile("bts %1,%0" : BITOP_ADDR(addr) : "Ir" (nr) : "memory"); } static inline void _tg3_flag_set(enum TG3_FLAGS flag, unsigned long *bits) { - unsigned int index = ( flag / ( 8 * sizeof ( *bits ) ) ); - unsigned int bit = ( flag % ( 8 * sizeof ( *bits ) ) ); - bits[index] |= ( 1UL << bit ); + __set_bit(flag, bits); +} + +static inline void __clear_bit(int nr, volatile unsigned long *addr) +{ + asm volatile("btr %1,%0" : BITOP_ADDR(addr) : "Ir" (nr)); } static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) { - unsigned int index = ( flag / ( 8 * sizeof ( *bits ) ) ); - unsigned int bit = ( flag % ( 8 * sizeof ( *bits ) ) ); - bits[index] &= ~( 1UL << bit ); + __clear_bit(flag, bits); } #define tg3_flag(tp, flag) \ diff --git a/roms/ipxe/src/drivers/net/thunderx.c b/roms/ipxe/src/drivers/net/thunderx.c deleted file mode 100644 index 306adc459..000000000 --- a/roms/ipxe/src/drivers/net/thunderx.c +++ /dev/null @@ -1,1706 +0,0 @@ -/* - * Copyright (C) 2016 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <string.h> -#include <strings.h> -#include <stdio.h> -#include <unistd.h> -#include <errno.h> -#include <assert.h> -#include <byteswap.h> -#include <ipxe/netdevice.h> -#include <ipxe/ethernet.h> -#include <ipxe/if_ether.h> -#include <ipxe/iobuf.h> -#include <ipxe/malloc.h> -#include <ipxe/pci.h> -#include <ipxe/pciea.h> -#include <ipxe/umalloc.h> -#include "thunderx.h" -#include "thunderxcfg.h" - -/** @file - * - * Cavium ThunderX Ethernet driver - * - */ - -/** List of BGX Ethernet interfaces */ -static LIST_HEAD ( txnic_bgxs ); - -/** List of physical functions */ -static LIST_HEAD ( txnic_pfs ); - -/** Debug colour for physical function and BGX messages */ -#define TXNICCOL(x) ( &txnic_pfs + (x)->node ) - -/** Board configuration protocol */ -static EFI_THUNDER_CONFIG_PROTOCOL *txcfg; -EFI_REQUEST_PROTOCOL ( EFI_THUNDER_CONFIG_PROTOCOL, &txcfg ); - -/****************************************************************************** - * - * Diagnostics - * - ****************************************************************************** - */ - -/** - * Show virtual NIC diagnostics (for debugging) - * - * @v vnic Virtual NIC - */ -static __attribute__ (( unused )) void txnic_diag ( struct txnic *vnic ) { - - DBGC ( vnic, "TXNIC %s SQ %05zx(%05llx)/%05zx(%05llx) %08llx\n", - vnic->name, - ( ( vnic->sq.prod % TXNIC_SQES ) * TXNIC_SQ_STRIDE ), - readq ( vnic->regs + TXNIC_QS_SQ_TAIL(0) ), - ( ( vnic->sq.cons % TXNIC_SQES ) * TXNIC_SQ_STRIDE ), - readq ( vnic->regs + TXNIC_QS_SQ_HEAD(0) ), - readq ( vnic->regs + TXNIC_QS_SQ_STATUS(0) ) ); - DBGC ( vnic, "TXNIC %s RQ %05zx(%05llx)/%05zx(%05llx) %016llx\n", - vnic->name, - ( ( vnic->rq.prod % TXNIC_RQES ) * TXNIC_RQ_STRIDE ), - readq ( vnic->regs + TXNIC_QS_RBDR_TAIL(0) ), - ( ( vnic->rq.cons % TXNIC_RQES ) * TXNIC_RQ_STRIDE ), - readq ( vnic->regs + TXNIC_QS_RBDR_HEAD(0) ), - readq ( vnic->regs + TXNIC_QS_RBDR_STATUS0(0) ) ); - DBGC ( vnic, "TXNIC %s CQ xxxxx(%05llx)/%05x(%05llx) %08llx:%08llx\n", - vnic->name, readq ( vnic->regs + TXNIC_QS_CQ_TAIL(0) ), - ( ( vnic->cq.cons % TXNIC_CQES ) * TXNIC_CQ_STRIDE ), - readq ( vnic->regs + TXNIC_QS_CQ_HEAD(0) ), - readq ( vnic->regs + TXNIC_QS_CQ_STATUS(0) ), - readq ( vnic->regs + TXNIC_QS_CQ_STATUS2(0) ) ); -} - -/****************************************************************************** - * - * Send queue - * - ****************************************************************************** - */ - -/** - * Create send queue - * - * @v vnic Virtual NIC - * @ret rc Return status code - */ -static int txnic_create_sq ( struct txnic *vnic ) { - - /* Reset send queue */ - vnic->sq.prod = 0; - vnic->sq.cons = 0; - writeq ( TXNIC_QS_SQ_CFG_RESET, ( vnic->regs + TXNIC_QS_SQ_CFG(0) ) ); - - /* Configure and enable send queue */ - writeq ( user_to_phys ( vnic->sq.sqe, 0 ), - ( vnic->regs + TXNIC_QS_SQ_BASE(0) ) ); - writeq ( ( TXNIC_QS_SQ_CFG_ENA | TXNIC_QS_SQ_CFG_QSIZE_1K ), - ( vnic->regs + TXNIC_QS_SQ_CFG(0) ) ); - - DBGC ( vnic, "TXNIC %s SQ at [%08lx,%08lx)\n", - vnic->name, user_to_phys ( vnic->sq.sqe, 0 ), - user_to_phys ( vnic->sq.sqe, TXNIC_SQ_SIZE ) ); - return 0; -} - -/** - * Disable send queue - * - * @v vnic Virtual NIC - * @ret rc Return status code - */ -static int txnic_disable_sq ( struct txnic *vnic ) { - uint64_t status; - unsigned int i; - - /* Disable send queue */ - writeq ( 0, ( vnic->regs + TXNIC_QS_SQ_CFG(0) ) ); - - /* Wait for send queue to be stopped */ - for ( i = 0 ; i < TXNIC_SQ_STOP_MAX_WAIT_MS ; i++ ) { - - /* Check if send queue is stopped */ - status = readq ( vnic->regs + TXNIC_QS_SQ_STATUS(0) ); - if ( status & TXNIC_QS_SQ_STATUS_STOPPED ) - return 0; - - /* Delay */ - mdelay ( 1 ); - } - - DBGC ( vnic, "TXNIC %s SQ disable timed out\n", vnic->name ); - return -ETIMEDOUT; -} - -/** - * Destroy send queue - * - * @v vnic Virtual NIC - */ -static void txnic_destroy_sq ( struct txnic *vnic ) { - int rc; - - /* Disable send queue */ - if ( ( rc = txnic_disable_sq ( vnic ) ) != 0 ) { - /* Nothing else we can do */ - return; - } - - /* Reset send queue */ - writeq ( TXNIC_QS_SQ_CFG_RESET, ( vnic->regs + TXNIC_QS_SQ_CFG(0) ) ); -} - -/** - * Send packet - * - * @v vnic Virtual NIC - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int txnic_send ( struct txnic *vnic, struct io_buffer *iobuf ) { - struct txnic_sqe sqe; - unsigned int sq_idx; - size_t offset; - size_t len; - - /* Get next send queue entry */ - if ( ( vnic->sq.prod - vnic->sq.cons ) >= TXNIC_SQ_FILL ) { - DBGC ( vnic, "TXNIC %s out of send queue entries\n", - vnic->name ); - return -ENOBUFS; - } - sq_idx = ( vnic->sq.prod++ % TXNIC_SQES ); - offset = ( sq_idx * TXNIC_SQ_STRIDE ); - - /* Populate send descriptor */ - len = iob_len ( iobuf ); - memset ( &sqe, 0, sizeof ( sqe ) ); - sqe.hdr.total = cpu_to_le32 ( ( len >= ETH_ZLEN ) ? len : ETH_ZLEN ); - sqe.hdr.subdcnt = ( TXNIC_SQE_SUBDESCS - 1 ); - sqe.hdr.flags = TXNIC_SEND_HDR_FLAGS; - sqe.gather.size = cpu_to_le16 ( len ); - sqe.gather.flags = TXNIC_SEND_GATHER_FLAGS; - sqe.gather.addr = cpu_to_le64 ( virt_to_bus ( iobuf->data ) ); - DBGC2 ( vnic, "TXNIC %s SQE %#03x is [%08lx,%08lx)\n", - vnic->name, sq_idx, virt_to_bus ( iobuf->data ), - ( virt_to_bus ( iobuf->data ) + len ) ); - - /* Copy send descriptor to ring */ - copy_to_user ( vnic->sq.sqe, offset, &sqe, sizeof ( sqe ) ); - - /* Ring doorbell */ - wmb(); - writeq ( TXNIC_SQE_SUBDESCS, ( vnic->regs + TXNIC_QS_SQ_DOOR(0) ) ); - - return 0; -} - -/** - * Complete send queue entry - * - * @v vnic Virtual NIC - * @v cqe Send completion queue entry - */ -static void txnic_complete_sqe ( struct txnic *vnic, - struct txnic_cqe_send *cqe ) { - struct net_device *netdev = vnic->netdev; - unsigned int sq_idx; - unsigned int status; - - /* Parse completion */ - sq_idx = ( le16_to_cpu ( cqe->sqe_ptr ) / TXNIC_SQE_SUBDESCS ); - status = cqe->send_status; - - /* Sanity check */ - assert ( sq_idx == ( vnic->sq.cons % TXNIC_SQES ) ); - - /* Free send queue entry */ - vnic->sq.cons++; - - /* Complete transmission */ - if ( status ) { - DBGC ( vnic, "TXNIC %s SQE %#03x complete (status %#02x)\n", - vnic->name, sq_idx, status ); - netdev_tx_complete_next_err ( netdev, -EIO ); - } else { - DBGC2 ( vnic, "TXNIC %s SQE %#03x complete\n", - vnic->name, sq_idx ); - netdev_tx_complete_next ( netdev ); - } -} - -/****************************************************************************** - * - * Receive queue - * - ****************************************************************************** - */ - -/** - * Create receive queue - * - * @v vnic Virtual NIC - * @ret rc Return status code - */ -static int txnic_create_rq ( struct txnic *vnic ) { - - /* Reset receive buffer descriptor ring */ - vnic->rq.prod = 0; - vnic->rq.cons = 0; - writeq ( TXNIC_QS_RBDR_CFG_RESET, - ( vnic->regs + TXNIC_QS_RBDR_CFG(0) ) ); - - /* Configure and enable receive buffer descriptor ring */ - writeq ( user_to_phys ( vnic->rq.rqe, 0 ), - ( vnic->regs + TXNIC_QS_RBDR_BASE(0) ) ); - writeq ( ( TXNIC_QS_RBDR_CFG_ENA | TXNIC_QS_RBDR_CFG_QSIZE_8K | - TXNIC_QS_RBDR_CFG_LINES ( TXNIC_RQE_SIZE / - TXNIC_LINE_SIZE ) ), - ( vnic->regs + TXNIC_QS_RBDR_CFG(0) ) ); - - /* Enable receive queue */ - writeq ( TXNIC_QS_RQ_CFG_ENA, ( vnic->regs + TXNIC_QS_RQ_CFG(0) ) ); - - DBGC ( vnic, "TXNIC %s RQ at [%08lx,%08lx)\n", - vnic->name, user_to_phys ( vnic->rq.rqe, 0 ), - user_to_phys ( vnic->rq.rqe, TXNIC_RQ_SIZE ) ); - return 0; -} - -/** - * Disable receive queue - * - * @v vnic Virtual NIC - * @ret rc Return status code - */ -static int txnic_disable_rq ( struct txnic *vnic ) { - uint64_t cfg; - unsigned int i; - - /* Disable receive queue */ - writeq ( 0, ( vnic->regs + TXNIC_QS_RQ_CFG(0) ) ); - - /* Wait for receive queue to be disabled */ - for ( i = 0 ; i < TXNIC_RQ_DISABLE_MAX_WAIT_MS ; i++ ) { - - /* Check if receive queue is disabled */ - cfg = readq ( vnic->regs + TXNIC_QS_RQ_CFG(0) ); - if ( ! ( cfg & TXNIC_QS_RQ_CFG_ENA ) ) - return 0; - - /* Delay */ - mdelay ( 1 ); - } - - DBGC ( vnic, "TXNIC %s RQ disable timed out\n", vnic->name ); - return -ETIMEDOUT; -} - -/** - * Destroy receive queue - * - * @v vnic Virtual NIC - */ -static void txnic_destroy_rq ( struct txnic *vnic ) { - unsigned int i; - int rc; - - /* Disable receive queue */ - if ( ( rc = txnic_disable_rq ( vnic ) ) != 0 ) { - /* Leak memory; there's nothing else we can do */ - return; - } - - /* Disable receive buffer descriptor ring */ - writeq ( 0, ( vnic->regs + TXNIC_QS_RBDR_CFG(0) ) ); - - /* Reset receive buffer descriptor ring */ - writeq ( TXNIC_QS_RBDR_CFG_RESET, - ( vnic->regs + TXNIC_QS_RBDR_CFG(0) ) ); - - /* Free any unused I/O buffers */ - for ( i = 0 ; i < TXNIC_RQ_FILL ; i++ ) { - if ( vnic->rq.iobuf[i] ) - free_iob ( vnic->rq.iobuf[i] ); - vnic->rq.iobuf[i] = NULL; - } -} - -/** - * Refill receive queue - * - * @v vnic Virtual NIC - */ -static void txnic_refill_rq ( struct txnic *vnic ) { - struct io_buffer *iobuf; - struct txnic_rqe rqe; - unsigned int rq_idx; - unsigned int rq_iobuf_idx; - unsigned int refilled = 0; - size_t offset; - - /* Refill ring */ - while ( ( vnic->rq.prod - vnic->rq.cons ) < TXNIC_RQ_FILL ) { - - /* Allocate I/O buffer */ - iobuf = alloc_iob ( TXNIC_RQE_SIZE ); - if ( ! iobuf ) { - /* Wait for next refill */ - break; - } - - /* Get next receive descriptor */ - rq_idx = ( vnic->rq.prod++ % TXNIC_RQES ); - offset = ( rq_idx * TXNIC_RQ_STRIDE ); - - /* Populate receive descriptor */ - rqe.rbdre.addr = cpu_to_le64 ( virt_to_bus ( iobuf->data ) ); - DBGC2 ( vnic, "TXNIC %s RQE %#03x is [%08lx,%08lx)\n", - vnic->name, rq_idx, virt_to_bus ( iobuf->data ), - ( virt_to_bus ( iobuf->data ) + TXNIC_RQE_SIZE ) ); - - /* Copy receive descriptor to ring */ - copy_to_user ( vnic->rq.rqe, offset, &rqe, sizeof ( rqe ) ); - refilled++; - - /* Record I/O buffer */ - rq_iobuf_idx = ( rq_idx % TXNIC_RQ_FILL ); - assert ( vnic->rq.iobuf[rq_iobuf_idx] == NULL ); - vnic->rq.iobuf[rq_iobuf_idx] = iobuf; - } - - /* Ring doorbell */ - wmb(); - writeq ( refilled, ( vnic->regs + TXNIC_QS_RBDR_DOOR(0) ) ); -} - -/** - * Complete receive queue entry - * - * @v vnic Virtual NIC - * @v cqe Receive completion queue entry - */ -static void txnic_complete_rqe ( struct txnic *vnic, - struct txnic_cqe_rx *cqe ) { - struct net_device *netdev = vnic->netdev; - struct io_buffer *iobuf; - unsigned int errop; - unsigned int rq_idx; - unsigned int rq_iobuf_idx; - size_t apad_len; - size_t len; - - /* Parse completion */ - errop = cqe->errop; - apad_len = TXNIC_CQE_RX_APAD_LEN ( cqe->apad ); - len = le16_to_cpu ( cqe->len ); - - /* Get next receive I/O buffer */ - rq_idx = ( vnic->rq.cons++ % TXNIC_RQES ); - rq_iobuf_idx = ( rq_idx % TXNIC_RQ_FILL ); - iobuf = vnic->rq.iobuf[rq_iobuf_idx]; - vnic->rq.iobuf[rq_iobuf_idx] = NULL; - - /* Populate I/O buffer */ - iob_reserve ( iobuf, apad_len ); - iob_put ( iobuf, len ); - - /* Hand off to network stack */ - if ( errop ) { - DBGC ( vnic, "TXNIC %s RQE %#03x error (length %zd, errop " - "%#02x)\n", vnic->name, rq_idx, len, errop ); - netdev_rx_err ( netdev, iobuf, -EIO ); - } else { - DBGC2 ( vnic, "TXNIC %s RQE %#03x complete (length %zd)\n", - vnic->name, rq_idx, len ); - netdev_rx ( netdev, iobuf ); - } -} - -/****************************************************************************** - * - * Completion queue - * - ****************************************************************************** - */ - -/** - * Create completion queue - * - * @v vnic Virtual NIC - * @ret rc Return status code - */ -static int txnic_create_cq ( struct txnic *vnic ) { - - /* Reset completion queue */ - vnic->cq.cons = 0; - writeq ( TXNIC_QS_CQ_CFG_RESET, ( vnic->regs + TXNIC_QS_CQ_CFG(0) ) ); - - /* Configure and enable completion queue */ - writeq ( user_to_phys ( vnic->cq.cqe, 0 ), - ( vnic->regs + TXNIC_QS_CQ_BASE(0) ) ); - writeq ( ( TXNIC_QS_CQ_CFG_ENA | TXNIC_QS_CQ_CFG_QSIZE_256 ), - ( vnic->regs + TXNIC_QS_CQ_CFG(0) ) ); - - DBGC ( vnic, "TXNIC %s CQ at [%08lx,%08lx)\n", - vnic->name, user_to_phys ( vnic->cq.cqe, 0 ), - user_to_phys ( vnic->cq.cqe, TXNIC_CQ_SIZE ) ); - return 0; -} - -/** - * Disable completion queue - * - * @v vnic Virtual NIC - * @ret rc Return status code - */ -static int txnic_disable_cq ( struct txnic *vnic ) { - uint64_t cfg; - unsigned int i; - - /* Disable completion queue */ - writeq ( 0, ( vnic->regs + TXNIC_QS_CQ_CFG(0) ) ); - - /* Wait for completion queue to be disabled */ - for ( i = 0 ; i < TXNIC_CQ_DISABLE_MAX_WAIT_MS ; i++ ) { - - /* Check if completion queue is disabled */ - cfg = readq ( vnic->regs + TXNIC_QS_CQ_CFG(0) ); - if ( ! ( cfg & TXNIC_QS_CQ_CFG_ENA ) ) - return 0; - - /* Delay */ - mdelay ( 1 ); - } - - DBGC ( vnic, "TXNIC %s CQ disable timed out\n", vnic->name ); - return -ETIMEDOUT; -} - -/** - * Destroy completion queue - * - * @v vnic Virtual NIC - */ -static void txnic_destroy_cq ( struct txnic *vnic ) { - int rc; - - /* Disable completion queue */ - if ( ( rc = txnic_disable_cq ( vnic ) ) != 0 ) { - /* Leak memory; there's nothing else we can do */ - return; - } - - /* Reset completion queue */ - writeq ( TXNIC_QS_CQ_CFG_RESET, ( vnic->regs + TXNIC_QS_CQ_CFG(0) ) ); -} - -/** - * Poll completion queue - * - * @v vnic Virtual NIC - */ -static void txnic_poll_cq ( struct txnic *vnic ) { - union txnic_cqe cqe; - uint64_t status; - size_t offset; - unsigned int qcount; - unsigned int cq_idx; - unsigned int i; - - /* Get number of completions */ - status = readq ( vnic->regs + TXNIC_QS_CQ_STATUS(0) ); - qcount = TXNIC_QS_CQ_STATUS_QCOUNT ( status ); - if ( ! qcount ) - return; - - /* Process completion queue entries */ - for ( i = 0 ; i < qcount ; i++ ) { - - /* Get completion queue entry */ - cq_idx = ( vnic->cq.cons++ % TXNIC_CQES ); - offset = ( cq_idx * TXNIC_CQ_STRIDE ); - copy_from_user ( &cqe, vnic->cq.cqe, offset, sizeof ( cqe ) ); - - /* Process completion queue entry */ - switch ( cqe.common.cqe_type ) { - case TXNIC_CQE_TYPE_SEND: - txnic_complete_sqe ( vnic, &cqe.send ); - break; - case TXNIC_CQE_TYPE_RX: - txnic_complete_rqe ( vnic, &cqe.rx ); - break; - default: - DBGC ( vnic, "TXNIC %s unknown completion type %d\n", - vnic->name, cqe.common.cqe_type ); - DBGC_HDA ( vnic, user_to_phys ( vnic->cq.cqe, offset ), - &cqe, sizeof ( cqe ) ); - break; - } - } - - /* Ring doorbell */ - writeq ( qcount, ( vnic->regs + TXNIC_QS_CQ_DOOR(0) ) ); -} - -/****************************************************************************** - * - * Virtual NIC - * - ****************************************************************************** - */ - -/** - * Open virtual NIC - * - * @v vnic Virtual NIC - * @ret rc Return status code - */ -static int txnic_open ( struct txnic *vnic ) { - int rc; - - /* Create completion queue */ - if ( ( rc = txnic_create_cq ( vnic ) ) != 0 ) - goto err_create_cq; - - /* Create send queue */ - if ( ( rc = txnic_create_sq ( vnic ) ) != 0 ) - goto err_create_sq; - - /* Create receive queue */ - if ( ( rc = txnic_create_rq ( vnic ) ) != 0 ) - goto err_create_rq; - - /* Refill receive queue */ - txnic_refill_rq ( vnic ); - - return 0; - - txnic_destroy_rq ( vnic ); - err_create_rq: - txnic_destroy_sq ( vnic ); - err_create_sq: - txnic_destroy_cq ( vnic ); - err_create_cq: - return rc; -} - -/** - * Close virtual NIC - * - * @v vnic Virtual NIC - */ -static void txnic_close ( struct txnic *vnic ) { - - /* Destroy receive queue */ - txnic_destroy_rq ( vnic ); - - /* Destroy send queue */ - txnic_destroy_sq ( vnic ); - - /* Destroy completion queue */ - txnic_destroy_cq ( vnic ); -} - -/** - * Poll virtual NIC - * - * @v vnic Virtual NIC - */ -static void txnic_poll ( struct txnic *vnic ) { - - /* Poll completion queue */ - txnic_poll_cq ( vnic ); - - /* Refill receive queue */ - txnic_refill_rq ( vnic ); -} - -/** - * Allocate virtual NIC - * - * @v dev Underlying device - * @v membase Register base address - * @ret vnic Virtual NIC, or NULL on failure - */ -static struct txnic * txnic_alloc ( struct device *dev, - unsigned long membase ) { - struct net_device *netdev; - struct txnic *vnic; - - /* Allocate network device */ - netdev = alloc_etherdev ( sizeof ( *vnic ) ); - if ( ! netdev ) - goto err_alloc_netdev; - netdev->dev = dev; - vnic = netdev->priv; - vnic->netdev = netdev; - vnic->name = dev->name; - - /* Allow caller to reuse netdev->priv. (The generic virtual - * NIC code never assumes that netdev->priv==vnic.) - */ - netdev->priv = NULL; - - /* Allocate completion queue */ - vnic->cq.cqe = umalloc ( TXNIC_CQ_SIZE ); - if ( ! vnic->cq.cqe ) - goto err_alloc_cq; - - /* Allocate send queue */ - vnic->sq.sqe = umalloc ( TXNIC_SQ_SIZE ); - if ( ! vnic->sq.sqe ) - goto err_alloc_sq; - - /* Allocate receive queue */ - vnic->rq.rqe = umalloc ( TXNIC_RQ_SIZE ); - if ( ! vnic->rq.rqe ) - goto err_alloc_rq; - - /* Map registers */ - vnic->regs = ioremap ( membase, TXNIC_VF_BAR_SIZE ); - if ( ! vnic->regs ) - goto err_ioremap; - - return vnic; - - iounmap ( vnic->regs ); - err_ioremap: - ufree ( vnic->rq.rqe ); - err_alloc_rq: - ufree ( vnic->sq.sqe ); - err_alloc_sq: - ufree ( vnic->cq.cqe ); - err_alloc_cq: - netdev_nullify ( netdev ); - netdev_put ( netdev ); - err_alloc_netdev: - return NULL; -} - -/** - * Free virtual NIC - * - * @v vnic Virtual NIC - */ -static void txnic_free ( struct txnic *vnic ) { - struct net_device *netdev = vnic->netdev; - - /* Unmap registers */ - iounmap ( vnic->regs ); - - /* Free receive queue */ - ufree ( vnic->rq.rqe ); - - /* Free send queue */ - ufree ( vnic->sq.sqe ); - - /* Free completion queue */ - ufree ( vnic->cq.cqe ); - - /* Free network device */ - netdev_nullify ( netdev ); - netdev_put ( netdev ); -} - -/****************************************************************************** - * - * Logical MAC virtual NICs - * - ****************************************************************************** - */ - -/** - * Show LMAC diagnostics (for debugging) - * - * @v lmac Logical MAC - */ -static __attribute__ (( unused )) void -txnic_lmac_diag ( struct txnic_lmac *lmac ) { - struct txnic *vnic = lmac->vnic; - uint64_t status1; - uint64_t status2; - uint64_t br_status1; - uint64_t br_status2; - uint64_t br_algn_status; - uint64_t br_pmd_status; - uint64_t an_status; - - /* Read status (clearing latching bits) */ - writeq ( BGX_SPU_STATUS1_RCV_LNK, ( lmac->regs + BGX_SPU_STATUS1 ) ); - writeq ( BGX_SPU_STATUS2_RCVFLT, ( lmac->regs + BGX_SPU_STATUS2 ) ); - status1 = readq ( lmac->regs + BGX_SPU_STATUS1 ); - status2 = readq ( lmac->regs + BGX_SPU_STATUS2 ); - DBGC ( vnic, "TXNIC %s SPU %02llx:%04llx%s%s%s\n", - vnic->name, status1, status2, - ( ( status1 & BGX_SPU_STATUS1_FLT ) ? " FLT" : "" ), - ( ( status1 & BGX_SPU_STATUS1_RCV_LNK ) ? " RCV_LNK" : "" ), - ( ( status2 & BGX_SPU_STATUS2_RCVFLT ) ? " RCVFLT" : "" ) ); - - /* Read BASE-R status (clearing latching bits) */ - writeq ( ( BGX_SPU_BR_STATUS2_LATCHED_LOCK | - BGX_SPU_BR_STATUS2_LATCHED_BER ), - ( lmac->regs + BGX_SPU_BR_STATUS2 ) ); - br_status1 = readq ( lmac->regs + BGX_SPU_BR_STATUS1 ); - br_status2 = readq ( lmac->regs + BGX_SPU_BR_STATUS2 ); - DBGC ( vnic, "TXNIC %s BR %04llx:%04llx%s%s%s%s%s\n", - vnic->name, br_status2, br_status2, - ( ( br_status1 & BGX_SPU_BR_STATUS1_RCV_LNK ) ? " RCV_LNK" : ""), - ( ( br_status1 & BGX_SPU_BR_STATUS1_HI_BER ) ? " HI_BER" : "" ), - ( ( br_status1 & BGX_SPU_BR_STATUS1_BLK_LOCK ) ? - " BLK_LOCK" : "" ), - ( ( br_status2 & BGX_SPU_BR_STATUS2_LATCHED_LOCK ) ? - " LATCHED_LOCK" : "" ), - ( ( br_status2 & BGX_SPU_BR_STATUS2_LATCHED_BER ) ? - " LATCHED_BER" : "" ) ); - - /* Read BASE-R alignment status */ - br_algn_status = readq ( lmac->regs + BGX_SPU_BR_ALGN_STATUS ); - DBGC ( vnic, "TXNIC %s BR ALGN %016llx%s\n", vnic->name, br_algn_status, - ( ( br_algn_status & BGX_SPU_BR_ALGN_STATUS_ALIGND ) ? - " ALIGND" : "" ) ); - - /* Read BASE-R link training status */ - br_pmd_status = readq ( lmac->regs + BGX_SPU_BR_PMD_STATUS ); - DBGC ( vnic, "TXNIC %s BR PMD %04llx\n", vnic->name, br_pmd_status ); - - /* Read autonegotiation status (clearing latching bits) */ - writeq ( ( BGX_SPU_AN_STATUS_PAGE_RX | BGX_SPU_AN_STATUS_LINK_STATUS ), - ( lmac->regs + BGX_SPU_AN_STATUS ) ); - an_status = readq ( lmac->regs + BGX_SPU_AN_STATUS ); - DBGC ( vnic, "TXNIC %s BR AN %04llx%s%s%s%s%s\n", vnic->name, an_status, - ( ( an_status & BGX_SPU_AN_STATUS_XNP_STAT ) ? " XNP_STAT" : ""), - ( ( an_status & BGX_SPU_AN_STATUS_PAGE_RX ) ? " PAGE_RX" : "" ), - ( ( an_status & BGX_SPU_AN_STATUS_AN_COMPLETE ) ? - " AN_COMPLETE" : "" ), - ( ( an_status & BGX_SPU_AN_STATUS_LINK_STATUS ) ? - " LINK_STATUS" : "" ), - ( ( an_status & BGX_SPU_AN_STATUS_LP_AN_ABLE ) ? - " LP_AN_ABLE" : "" ) ); - - /* Read transmit statistics */ - DBGC ( vnic, "TXNIC %s TXF xc %#llx xd %#llx mc %#llx sc %#llx ok " - "%#llx bc %#llx mc %#llx un %#llx pa %#llx\n", vnic->name, - readq ( lmac->regs + BGX_CMR_TX_STAT0 ), - readq ( lmac->regs + BGX_CMR_TX_STAT1 ), - readq ( lmac->regs + BGX_CMR_TX_STAT2 ), - readq ( lmac->regs + BGX_CMR_TX_STAT3 ), - readq ( lmac->regs + BGX_CMR_TX_STAT5 ), - readq ( lmac->regs + BGX_CMR_TX_STAT14 ), - readq ( lmac->regs + BGX_CMR_TX_STAT15 ), - readq ( lmac->regs + BGX_CMR_TX_STAT16 ), - readq ( lmac->regs + BGX_CMR_TX_STAT17 ) ); - DBGC ( vnic, "TXNIC %s TXB ok %#llx hist %#llx:%#llx:%#llx:%#llx:" - "%#llx:%#llx:%#llx:%#llx\n", vnic->name, - readq ( lmac->regs + BGX_CMR_TX_STAT4 ), - readq ( lmac->regs + BGX_CMR_TX_STAT6 ), - readq ( lmac->regs + BGX_CMR_TX_STAT7 ), - readq ( lmac->regs + BGX_CMR_TX_STAT8 ), - readq ( lmac->regs + BGX_CMR_TX_STAT9 ), - readq ( lmac->regs + BGX_CMR_TX_STAT10 ), - readq ( lmac->regs + BGX_CMR_TX_STAT11 ), - readq ( lmac->regs + BGX_CMR_TX_STAT12 ), - readq ( lmac->regs + BGX_CMR_TX_STAT13 ) ); - - /* Read receive statistics */ - DBGC ( vnic, "TXNIC %s RXF ok %#llx pa %#llx nm %#llx ov %#llx er " - "%#llx nc %#llx\n", vnic->name, - readq ( lmac->regs + BGX_CMR_RX_STAT0 ), - readq ( lmac->regs + BGX_CMR_RX_STAT2 ), - readq ( lmac->regs + BGX_CMR_RX_STAT4 ), - readq ( lmac->regs + BGX_CMR_RX_STAT6 ), - readq ( lmac->regs + BGX_CMR_RX_STAT8 ), - readq ( lmac->regs + BGX_CMR_RX_STAT9 ) ); - DBGC ( vnic, "TXNIC %s RXB ok %#llx pa %#llx nm %#llx ov %#llx nc " - "%#llx\n", vnic->name, - readq ( lmac->regs + BGX_CMR_RX_STAT1 ), - readq ( lmac->regs + BGX_CMR_RX_STAT3 ), - readq ( lmac->regs + BGX_CMR_RX_STAT5 ), - readq ( lmac->regs + BGX_CMR_RX_STAT7 ), - readq ( lmac->regs + BGX_CMR_RX_STAT10 ) ); -} - -/** - * Update LMAC link state - * - * @v lmac Logical MAC - */ -static void txnic_lmac_update_link ( struct txnic_lmac *lmac ) { - struct txnic *vnic = lmac->vnic; - struct net_device *netdev = vnic->netdev; - uint64_t status1; - - /* Read status (clearing latching bits) */ - writeq ( BGX_SPU_STATUS1_RCV_LNK, ( lmac->regs + BGX_SPU_STATUS1 ) ); - status1 = readq ( lmac->regs + BGX_SPU_STATUS1 ); - - /* Report link status */ - if ( status1 & BGX_SPU_STATUS1_RCV_LNK ) { - netdev_link_up ( netdev ); - } else { - netdev_link_down ( netdev ); - } -} - -/** - * Poll LMAC link state - * - * @v lmac Logical MAC - */ -static void txnic_lmac_poll_link ( struct txnic_lmac *lmac ) { - struct txnic *vnic = lmac->vnic; - uint64_t intr; - - /* Get interrupt status */ - intr = readq ( lmac->regs + BGX_SPU_INT ); - if ( ! intr ) - return; - DBGC ( vnic, "TXNIC %s INT %04llx%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", - vnic->name, intr, - ( ( intr & BGX_SPU_INT_TRAINING_FAIL ) ? " TRAINING_FAIL" : "" ), - ( ( intr & BGX_SPU_INT_TRAINING_DONE ) ? " TRAINING_DONE" : "" ), - ( ( intr & BGX_SPU_INT_AN_COMPLETE ) ? " AN_COMPLETE" : "" ), - ( ( intr & BGX_SPU_INT_AN_LINK_GOOD ) ? " AN_LINK_GOOD" : "" ), - ( ( intr & BGX_SPU_INT_AN_PAGE_RX ) ? " AN_PAGE_RX" : "" ), - ( ( intr & BGX_SPU_INT_FEC_UNCORR ) ? " FEC_UNCORR" : "" ), - ( ( intr & BGX_SPU_INT_FEC_CORR ) ? " FEC_CORR" : "" ), - ( ( intr & BGX_SPU_INT_BIP_ERR ) ? " BIP_ERR" : "" ), - ( ( intr & BGX_SPU_INT_DBG_SYNC ) ? " DBG_SYNC" : "" ), - ( ( intr & BGX_SPU_INT_ALGNLOS ) ? " ALGNLOS" : "" ), - ( ( intr & BGX_SPU_INT_SYNLOS ) ? " SYNLOS" : "" ), - ( ( intr & BGX_SPU_INT_BITLCKLS ) ? " BITLCKLS" : "" ), - ( ( intr & BGX_SPU_INT_ERR_BLK ) ? " ERR_BLK" : "" ), - ( ( intr & BGX_SPU_INT_RX_LINK_DOWN ) ? " RX_LINK_DOWN" : "" ), - ( ( intr & BGX_SPU_INT_RX_LINK_UP ) ? " RX_LINK_UP" : "" ) ); - - /* Clear interrupt status */ - writeq ( intr, ( lmac->regs + BGX_SPU_INT ) ); - - /* Update link state */ - txnic_lmac_update_link ( lmac ); -} - -/** - * Reset LMAC - * - * @v lmac Logical MAC - */ -static void txnic_lmac_reset ( struct txnic_lmac *lmac ) { - struct txnic_bgx *bgx = lmac->bgx; - struct txnic_pf *pf = bgx->pf; - void *qsregs = ( pf->regs + TXNIC_PF_QS ( lmac->idx ) ); - - /* There is no reset available for the physical function - * aspects of a virtual NIC; we have to explicitly reload a - * sensible set of default values. - */ - writeq ( 0, ( qsregs + TXNIC_PF_QS_CFG ) ); - writeq ( 0, ( qsregs + TXNIC_PF_QS_RQ_CFG(0) ) ); - writeq ( 0, ( qsregs + TXNIC_PF_QS_RQ_DROP_CFG(0) ) ); - writeq ( 0, ( qsregs + TXNIC_PF_QS_RQ_BP_CFG(0) ) ); - writeq ( 0, ( qsregs + TXNIC_PF_QS_SQ_CFG(0) ) ); -} - -/** - * Open network device - * - * @v netdev Network device - * @ret rc Return status code - */ -static int txnic_lmac_open ( struct net_device *netdev ) { - struct txnic_lmac *lmac = netdev->priv; - struct txnic_bgx *bgx = lmac->bgx; - struct txnic_pf *pf = bgx->pf; - struct txnic *vnic = lmac->vnic; - unsigned int vnic_idx = lmac->idx; - unsigned int chan_idx = TXNIC_CHAN_IDX ( vnic_idx ); - unsigned int tl4_idx = TXNIC_TL4_IDX ( vnic_idx ); - unsigned int tl3_idx = TXNIC_TL3_IDX ( vnic_idx ); - unsigned int tl2_idx = TXNIC_TL2_IDX ( vnic_idx ); - void *lmregs = ( pf->regs + TXNIC_PF_LMAC ( vnic_idx ) ); - void *chregs = ( pf->regs + TXNIC_PF_CHAN ( chan_idx ) ); - void *qsregs = ( pf->regs + TXNIC_PF_QS ( vnic_idx ) ); - size_t max_pkt_size; - int rc; - - /* Configure channel/match parse indices */ - writeq ( ( TXNIC_PF_MPI_CFG_VNIC ( vnic_idx ) | - TXNIC_PF_MPI_CFG_RSSI_BASE ( vnic_idx ) ), - ( TXNIC_PF_MPI_CFG ( vnic_idx ) + pf->regs ) ); - writeq ( ( TXNIC_PF_RSSI_RQ_RQ_QS ( vnic_idx ) ), - ( TXNIC_PF_RSSI_RQ ( vnic_idx ) + pf->regs ) ); - - /* Configure LMAC */ - max_pkt_size = ( netdev->max_pkt_len + 4 /* possible VLAN */ ); - writeq ( ( TXNIC_PF_LMAC_CFG_ADJUST_DEFAULT | - TXNIC_PF_LMAC_CFG_MIN_PKT_SIZE ( ETH_ZLEN ) ), - ( TXNIC_PF_LMAC_CFG + lmregs ) ); - writeq ( ( TXNIC_PF_LMAC_CFG2_MAX_PKT_SIZE ( max_pkt_size ) ), - ( TXNIC_PF_LMAC_CFG2 + lmregs ) ); - writeq ( ( TXNIC_PF_LMAC_CREDIT_CC_UNIT_CNT_DEFAULT | - TXNIC_PF_LMAC_CREDIT_CC_PACKET_CNT_DEFAULT | - TXNIC_PF_LMAC_CREDIT_CC_ENABLE ), - ( TXNIC_PF_LMAC_CREDIT + lmregs ) ); - - /* Configure channels */ - writeq ( ( TXNIC_PF_CHAN_TX_CFG_BP_ENA ), - ( TXNIC_PF_CHAN_TX_CFG + chregs ) ); - writeq ( ( TXNIC_PF_CHAN_RX_CFG_CPI_BASE ( vnic_idx ) ), - ( TXNIC_PF_CHAN_RX_CFG + chregs ) ); - writeq ( ( TXNIC_PF_CHAN_RX_BP_CFG_ENA | - TXNIC_PF_CHAN_RX_BP_CFG_BPID ( vnic_idx ) ), - ( TXNIC_PF_CHAN_RX_BP_CFG + chregs ) ); - - /* Configure traffic limiters */ - writeq ( ( TXNIC_PF_TL2_CFG_RR_QUANTUM_DEFAULT ), - ( TXNIC_PF_TL2_CFG ( tl2_idx ) + pf->regs ) ); - writeq ( ( TXNIC_PF_TL3_CFG_RR_QUANTUM_DEFAULT ), - ( TXNIC_PF_TL3_CFG ( tl3_idx ) + pf->regs ) ); - writeq ( ( TXNIC_PF_TL3_CHAN_CHAN ( chan_idx ) ), - ( TXNIC_PF_TL3_CHAN ( tl3_idx ) + pf->regs ) ); - writeq ( ( TXNIC_PF_TL4_CFG_SQ_QS ( vnic_idx ) | - TXNIC_PF_TL4_CFG_RR_QUANTUM_DEFAULT ), - ( TXNIC_PF_TL4_CFG ( tl4_idx ) + pf->regs ) ); - - /* Configure send queue */ - writeq ( ( TXNIC_PF_QS_SQ_CFG_CQ_QS ( vnic_idx ) ), - ( TXNIC_PF_QS_SQ_CFG(0) + qsregs ) ); - writeq ( ( TXNIC_PF_QS_SQ_CFG2_TL4 ( tl4_idx ) ), - ( TXNIC_PF_QS_SQ_CFG2(0) + qsregs ) ); - - /* Configure receive queue */ - writeq ( ( TXNIC_PF_QS_RQ_CFG_CACHING_ALL | - TXNIC_PF_QS_RQ_CFG_CQ_QS ( vnic_idx ) | - TXNIC_PF_QS_RQ_CFG_RBDR_CONT_QS ( vnic_idx ) | - TXNIC_PF_QS_RQ_CFG_RBDR_STRT_QS ( vnic_idx ) ), - ( TXNIC_PF_QS_RQ_CFG(0) + qsregs ) ); - writeq ( ( TXNIC_PF_QS_RQ_BP_CFG_RBDR_BP_ENA | - TXNIC_PF_QS_RQ_BP_CFG_CQ_BP_ENA | - TXNIC_PF_QS_RQ_BP_CFG_BPID ( vnic_idx ) ), - ( TXNIC_PF_QS_RQ_BP_CFG(0) + qsregs ) ); - - /* Enable queue set */ - writeq ( ( TXNIC_PF_QS_CFG_ENA | TXNIC_PF_QS_CFG_VNIC ( vnic_idx ) ), - ( TXNIC_PF_QS_CFG + qsregs ) ); - - /* Open virtual NIC */ - if ( ( rc = txnic_open ( vnic ) ) != 0 ) - goto err_open; - - /* Update link state */ - txnic_lmac_update_link ( lmac ); - - return 0; - - txnic_close ( vnic ); - err_open: - writeq ( 0, ( qsregs + TXNIC_PF_QS_CFG ) ); - return rc; -} - -/** - * Close network device - * - * @v netdev Network device - */ -static void txnic_lmac_close ( struct net_device *netdev ) { - struct txnic_lmac *lmac = netdev->priv; - struct txnic_bgx *bgx = lmac->bgx; - struct txnic_pf *pf = bgx->pf; - struct txnic *vnic = lmac->vnic; - void *qsregs = ( pf->regs + TXNIC_PF_QS ( lmac->idx ) ); - - /* Close virtual NIC */ - txnic_close ( vnic ); - - /* Disable queue set */ - writeq ( 0, ( qsregs + TXNIC_PF_QS_CFG ) ); -} - -/** - * Transmit packet - * - * @v netdev Network device - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int txnic_lmac_transmit ( struct net_device *netdev, - struct io_buffer *iobuf ) { - struct txnic_lmac *lmac = netdev->priv; - struct txnic *vnic = lmac->vnic; - - return txnic_send ( vnic, iobuf ); -} - -/** - * Poll network device - * - * @v netdev Network device - */ -static void txnic_lmac_poll ( struct net_device *netdev ) { - struct txnic_lmac *lmac = netdev->priv; - struct txnic *vnic = lmac->vnic; - - /* Poll virtual NIC */ - txnic_poll ( vnic ); - - /* Poll link state */ - txnic_lmac_poll_link ( lmac ); -} - -/** Network device operations */ -static struct net_device_operations txnic_lmac_operations = { - .open = txnic_lmac_open, - .close = txnic_lmac_close, - .transmit = txnic_lmac_transmit, - .poll = txnic_lmac_poll, -}; - -/** - * Probe logical MAC virtual NIC - * - * @v lmac Logical MAC - * @ret rc Return status code - */ -static int txnic_lmac_probe ( struct txnic_lmac *lmac ) { - struct txnic_bgx *bgx = lmac->bgx; - struct txnic_pf *pf = bgx->pf; - struct txnic *vnic; - struct net_device *netdev; - unsigned long membase; - int rc; - - /* Sanity check */ - assert ( lmac->vnic == NULL ); - - /* Calculate register base address */ - membase = ( pf->vf_membase + ( lmac->idx * pf->vf_stride ) ); - - /* Allocate and initialise network device */ - vnic = txnic_alloc ( &bgx->pci->dev, membase ); - if ( ! vnic ) { - rc = -ENOMEM; - goto err_alloc; - } - netdev = vnic->netdev; - netdev_init ( netdev, &txnic_lmac_operations ); - netdev->priv = lmac; - lmac->vnic = vnic; - - /* Reset device */ - txnic_lmac_reset ( lmac ); - - /* Set MAC address */ - memcpy ( netdev->hw_addr, lmac->mac.raw, ETH_ALEN ); - - /* Register network device */ - if ( ( rc = register_netdev ( netdev ) ) != 0 ) - goto err_register; - vnic->name = netdev->name; - DBGC ( TXNICCOL ( pf ), "TXNIC %d/%d/%d is %s (%s)\n", pf->node, - bgx->idx, lmac->idx, vnic->name, eth_ntoa ( lmac->mac.raw ) ); - - /* Update link state */ - txnic_lmac_update_link ( lmac ); - - return 0; - - unregister_netdev ( netdev ); - err_register: - txnic_lmac_reset ( lmac ); - txnic_free ( vnic ); - lmac->vnic = NULL; - err_alloc: - return rc; -} - -/** - * Remove logical MAC virtual NIC - * - * @v lmac Logical MAC - */ -static void txnic_lmac_remove ( struct txnic_lmac *lmac ) { - - /* Sanity check */ - assert ( lmac->vnic != NULL ); - - /* Unregister network device */ - unregister_netdev ( lmac->vnic->netdev ); - - /* Reset device */ - txnic_lmac_reset ( lmac ); - - /* Free virtual NIC */ - txnic_free ( lmac->vnic ); - lmac->vnic = NULL; -} - -/** - * Probe all LMACs on a BGX Ethernet interface - * - * @v pf Physical function - * @v bgx BGX Ethernet interface - * @ret rc Return status code - */ -static int txnic_lmac_probe_all ( struct txnic_pf *pf, struct txnic_bgx *bgx ) { - unsigned int bgx_idx; - int lmac_idx; - int count; - int rc; - - /* Sanity checks */ - bgx_idx = bgx->idx; - assert ( pf->node == bgx->node ); - assert ( pf->bgx[bgx_idx] == NULL ); - assert ( bgx->pf == NULL ); - - /* Associate BGX with physical function */ - pf->bgx[bgx_idx] = bgx; - bgx->pf = pf; - - /* Probe all LMACs */ - count = bgx->count; - for ( lmac_idx = 0 ; lmac_idx < count ; lmac_idx++ ) { - if ( ( rc = txnic_lmac_probe ( &bgx->lmac[lmac_idx] ) ) != 0 ) - goto err_probe; - } - - return 0; - - lmac_idx = count; - err_probe: - for ( lmac_idx-- ; lmac_idx >= 0 ; lmac_idx-- ) - txnic_lmac_remove ( &bgx->lmac[lmac_idx] ); - pf->bgx[bgx_idx] = NULL; - bgx->pf = NULL; - return rc; -} - -/** - * Remove all LMACs on a BGX Ethernet interface - * - * @v pf Physical function - * @v bgx BGX Ethernet interface - */ -static void txnic_lmac_remove_all ( struct txnic_pf *pf, - struct txnic_bgx *bgx ) { - unsigned int lmac_idx; - - /* Sanity checks */ - assert ( pf->bgx[bgx->idx] == bgx ); - assert ( bgx->pf == pf ); - - /* Remove all LMACs */ - for ( lmac_idx = 0 ; lmac_idx < bgx->count ; lmac_idx++ ) - txnic_lmac_remove ( &bgx->lmac[lmac_idx] ); - - /* Disassociate BGX from physical function */ - pf->bgx[bgx->idx] = NULL; - bgx->pf = NULL; -} - -/****************************************************************************** - * - * NIC physical function interface - * - ****************************************************************************** - */ - -/** - * Probe PCI device - * - * @v pci PCI device - * @ret rc Return status code - */ -static int txnic_pf_probe ( struct pci_device *pci ) { - struct txnic_pf *pf; - struct txnic_bgx *bgx; - unsigned long membase; - unsigned int i; - int rc; - - /* Allocate and initialise structure */ - pf = zalloc ( sizeof ( *pf ) ); - if ( ! pf ) { - rc = -ENOMEM; - goto err_alloc; - } - pf->pci = pci; - pci_set_drvdata ( pci, pf ); - - /* Get base addresses */ - membase = pciea_bar_start ( pci, PCIEA_BEI_BAR_0 ); - pf->vf_membase = pciea_bar_start ( pci, PCIEA_BEI_VF_BAR_0 ); - pf->vf_stride = pciea_bar_size ( pci, PCIEA_BEI_VF_BAR_0 ); - - /* Calculate node ID */ - pf->node = txnic_address_node ( membase ); - DBGC ( TXNICCOL ( pf ), "TXNIC %d/*/* PF %s at %#lx (VF %#lx+%#lx)\n", - pf->node, pci->dev.name, membase, pf->vf_membase, pf->vf_stride); - - /* Fix up PCI device */ - adjust_pci_device ( pci ); - - /* Map registers */ - pf->regs = ioremap ( membase, TXNIC_PF_BAR_SIZE ); - if ( ! pf->regs ) { - rc = -ENODEV; - goto err_ioremap; - } - - /* Configure physical function */ - writeq ( TXNIC_PF_CFG_ENA, ( pf->regs + TXNIC_PF_CFG ) ); - writeq ( ( TXNIC_PF_BP_CFG_BP_POLL_ENA | - TXNIC_PF_BP_CFG_BP_POLL_DLY_DEFAULT ), - ( pf->regs + TXNIC_PF_BP_CFG ) ); - for ( i = 0 ; i < TXNIC_NUM_BGX ; i++ ) { - writeq ( ( TXNIC_PF_INTF_SEND_CFG_BLOCK_BGX | - TXNIC_PF_INTF_SEND_CFG_BLOCK ( i ) ), - ( pf->regs + TXNIC_PF_INTF_SEND_CFG ( i ) ) ); - writeq ( ( TXNIC_PF_INTF_BP_CFG_BP_ENA | - TXNIC_PF_INTF_BP_CFG_BP_ID_BGX | - TXNIC_PF_INTF_BP_CFG_BP_ID ( i ) ), - ( pf->regs + TXNIC_PF_INTF_BP_CFG ( i ) ) ); - } - writeq ( ( TXNIC_PF_PKIND_CFG_LENERR_EN | - TXNIC_PF_PKIND_CFG_MAXLEN_DISABLE | - TXNIC_PF_PKIND_CFG_MINLEN_DISABLE ), - ( pf->regs + TXNIC_PF_PKIND_CFG(0) ) ); - - /* Add to list of physical functions */ - list_add_tail ( &pf->list, &txnic_pfs ); - - /* Probe all LMACs, if applicable */ - list_for_each_entry ( bgx, &txnic_bgxs, list ) { - if ( bgx->node != pf->node ) - continue; - if ( ( rc = txnic_lmac_probe_all ( pf, bgx ) ) != 0 ) - goto err_probe; - } - - return 0; - - err_probe: - for ( i = 0 ; i < TXNIC_NUM_BGX ; i++ ) { - if ( pf->bgx[i] ) - txnic_lmac_remove_all ( pf, pf->bgx[i] ); - } - list_del ( &pf->list ); - writeq ( 0, ( pf->regs + TXNIC_PF_CFG ) ); - iounmap ( pf->regs ); - err_ioremap: - free ( pf ); - err_alloc: - return rc; -} - -/** - * Remove PCI device - * - * @v pci PCI device - */ -static void txnic_pf_remove ( struct pci_device *pci ) { - struct txnic_pf *pf = pci_get_drvdata ( pci ); - unsigned int i; - - /* Remove all LMACs, if applicable */ - for ( i = 0 ; i < TXNIC_NUM_BGX ; i++ ) { - if ( pf->bgx[i] ) - txnic_lmac_remove_all ( pf, pf->bgx[i] ); - } - - /* Remove from list of physical functions */ - list_del ( &pf->list ); - - /* Disable physical function */ - writeq ( 0, ( pf->regs + TXNIC_PF_CFG ) ); - - /* Unmap registers */ - iounmap ( pf->regs ); - - /* Free physical function */ - free ( pf ); -} - -/** NIC physical function PCI device IDs */ -static struct pci_device_id txnic_pf_ids[] = { - PCI_ROM ( 0x177d, 0xa01e, "thunder-pf", "ThunderX NIC PF", 0 ), -}; - -/** NIC physical function PCI driver */ -struct pci_driver txnic_pf_driver __pci_driver = { - .ids = txnic_pf_ids, - .id_count = ( sizeof ( txnic_pf_ids ) / sizeof ( txnic_pf_ids[0] ) ), - .probe = txnic_pf_probe, - .remove = txnic_pf_remove, -}; - -/****************************************************************************** - * - * BGX interface - * - ****************************************************************************** - */ - -/** LMAC types */ -static struct txnic_lmac_type txnic_lmac_types[] = { - [TXNIC_LMAC_XAUI] = { - .name = "XAUI", - .count = 1, - .lane_to_sds = 0xe4, - }, - [TXNIC_LMAC_RXAUI] = { - .name = "RXAUI", - .count = 2, - .lane_to_sds = 0x0e04, - }, - [TXNIC_LMAC_10G_R] = { - .name = "10GBASE-R", - .count = 4, - .lane_to_sds = 0x00000000, - }, - [TXNIC_LMAC_40G_R] = { - .name = "40GBASE-R", - .count = 1, - .lane_to_sds = 0xe4, - }, -}; - -/** - * Detect BGX Ethernet interface LMAC type - * - * @v bgx BGX Ethernet interface - * @ret type LMAC type, or negative error - */ -static int txnic_bgx_detect ( struct txnic_bgx *bgx ) { - uint64_t config; - uint64_t br_pmd_control; - uint64_t rx_lmacs; - unsigned int type; - - /* We assume that the early (pre-UEFI) firmware will have - * configured at least the LMAC 0 type and use of link - * training, and may have overridden the number of LMACs. - */ - - /* Determine type from LMAC 0 */ - config = readq ( bgx->regs + BGX_CMR_CONFIG ); - type = BGX_CMR_CONFIG_LMAC_TYPE_GET ( config ); - if ( ( type >= ( sizeof ( txnic_lmac_types ) / - sizeof ( txnic_lmac_types[0] ) ) ) || - ( txnic_lmac_types[type].count == 0 ) ) { - DBGC ( TXNICCOL ( bgx ), "TXNIC %d/%d/* BGX unknown type %d\n", - bgx->node, bgx->idx, type ); - return -ENOTTY; - } - bgx->type = &txnic_lmac_types[type]; - - /* Check whether link training is required */ - br_pmd_control = readq ( bgx->regs + BGX_SPU_BR_PMD_CONTROL ); - bgx->training = - ( !! ( br_pmd_control & BGX_SPU_BR_PMD_CONTROL_TRAIN_EN ) ); - - /* Determine number of LMACs */ - rx_lmacs = readq ( bgx->regs + BGX_CMR_RX_LMACS ); - bgx->count = BGX_CMR_RX_LMACS_LMACS_GET ( rx_lmacs ); - if ( ( bgx->count == TXNIC_NUM_LMAC ) && - ( bgx->type->count != TXNIC_NUM_LMAC ) ) { - DBGC ( TXNICCOL ( bgx ), "TXNIC %d/%d/* assuming %d LMACs\n", - bgx->node, bgx->idx, bgx->type->count ); - bgx->count = bgx->type->count; - } - - return type; -} - -/** - * Initialise BGX Ethernet interface - * - * @v bgx BGX Ethernet interface - * @v type LMAC type - */ -static void txnic_bgx_init ( struct txnic_bgx *bgx, unsigned int type ) { - uint64_t global_config; - uint32_t lane_to_sds; - unsigned int i; - - /* Set number of LMACs */ - writeq ( BGX_CMR_RX_LMACS_LMACS_SET ( bgx->count ), - ( bgx->regs + BGX_CMR_RX_LMACS ) ); - writeq ( BGX_CMR_TX_LMACS_LMACS_SET ( bgx->count ), - ( bgx->regs + BGX_CMR_TX_LMACS ) ); - - /* Set LMAC types and lane mappings, and disable all LMACs */ - lane_to_sds = bgx->type->lane_to_sds; - for ( i = 0 ; i < bgx->count ; i++ ) { - writeq ( ( BGX_CMR_CONFIG_LMAC_TYPE_SET ( type ) | - BGX_CMR_CONFIG_LANE_TO_SDS ( lane_to_sds ) ), - ( bgx->regs + BGX_LMAC ( i ) + BGX_CMR_CONFIG ) ); - lane_to_sds >>= 8; - } - - /* Reset all MAC address filtering */ - for ( i = 0 ; i < TXNIC_NUM_DMAC ; i++ ) - writeq ( 0, ( bgx->regs + BGX_CMR_RX_DMAC_CAM ( i ) ) ); - - /* Reset NCSI steering */ - for ( i = 0 ; i < TXNIC_NUM_STEERING ; i++ ) - writeq ( 0, ( bgx->regs + BGX_CMR_RX_STEERING ( i ) ) ); - - /* Enable backpressure to all channels */ - writeq ( BGX_CMR_CHAN_MSK_AND_ALL ( bgx->count ), - ( bgx->regs + BGX_CMR_CHAN_MSK_AND ) ); - - /* Strip FCS */ - global_config = readq ( bgx->regs + BGX_CMR_GLOBAL_CONFIG ); - global_config |= BGX_CMR_GLOBAL_CONFIG_FCS_STRIP; - writeq ( global_config, ( bgx->regs + BGX_CMR_GLOBAL_CONFIG ) ); -} - -/** - * Get MAC address - * - * @v lmac Logical MAC - */ -static void txnic_bgx_mac ( struct txnic_lmac *lmac ) { - struct txnic_bgx *bgx = lmac->bgx; - BOARD_CFG *boardcfg; - NODE_CFG *nodecfg; - BGX_CFG *bgxcfg; - LMAC_CFG *lmaccfg; - - /* Extract MAC from Board Configuration protocol, if available */ - if ( txcfg ) { - boardcfg = txcfg->BoardConfig; - nodecfg = &boardcfg->Node[ bgx->node % MAX_NODES ]; - bgxcfg = &nodecfg->BgxCfg[ bgx->idx % BGX_PER_NODE_COUNT ]; - lmaccfg = &bgxcfg->Lmacs[ lmac->idx % LMAC_PER_BGX_COUNT ]; - lmac->mac.be64 = cpu_to_be64 ( lmaccfg->MacAddress ); - } else { - DBGC ( TXNICCOL ( bgx ), "TXNIC %d/%d/%d has no board " - "configuration protocol\n", bgx->node, bgx->idx, - lmac->idx ); - } - - /* Use random MAC address if none available */ - if ( ! lmac->mac.be64 ) { - DBGC ( TXNICCOL ( bgx ), "TXNIC %d/%d/%d has no MAC address\n", - bgx->node, bgx->idx, lmac->idx ); - eth_random_addr ( lmac->mac.raw ); - } -} - -/** - * Initialise Super PHY Unit (SPU) - * - * @v lmac Logical MAC - */ -static void txnic_bgx_spu_init ( struct txnic_lmac *lmac ) { - struct txnic_bgx *bgx = lmac->bgx; - - /* Reset PHY */ - writeq ( BGX_SPU_CONTROL1_RESET, ( lmac->regs + BGX_SPU_CONTROL1 ) ); - mdelay ( BGX_SPU_RESET_DELAY_MS ); - - /* Power down PHY */ - writeq ( BGX_SPU_CONTROL1_LO_PWR, ( lmac->regs + BGX_SPU_CONTROL1 ) ); - - /* Configure training, if applicable */ - if ( bgx->training ) { - writeq ( 0, ( lmac->regs + BGX_SPU_BR_PMD_LP_CUP ) ); - writeq ( 0, ( lmac->regs + BGX_SPU_BR_PMD_LD_CUP ) ); - writeq ( 0, ( lmac->regs + BGX_SPU_BR_PMD_LD_REP ) ); - writeq ( BGX_SPU_BR_PMD_CONTROL_TRAIN_EN, - ( lmac->regs + BGX_SPU_BR_PMD_CONTROL ) ); - } - - /* Disable forward error correction */ - writeq ( 0, ( lmac->regs + BGX_SPU_FEC_CONTROL ) ); - - /* Disable autonegotiation */ - writeq ( 0, ( lmac->regs + BGX_SPU_AN_CONTROL ) ); - - /* Power up PHY */ - writeq ( 0, ( lmac->regs + BGX_SPU_CONTROL1 ) ); -} - -/** - * Initialise LMAC - * - * @v bgx BGX Ethernet interface - * @v lmac_idx LMAC index - */ -static void txnic_bgx_lmac_init ( struct txnic_bgx *bgx, - unsigned int lmac_idx ) { - struct txnic_lmac *lmac = &bgx->lmac[lmac_idx]; - uint64_t config; - - /* Record associated BGX */ - lmac->bgx = bgx; - - /* Set register base address (already mapped) */ - lmac->regs = ( bgx->regs + BGX_LMAC ( lmac_idx ) ); - - /* Calculate virtual NIC index */ - lmac->idx = TXNIC_VNIC_IDX ( bgx->idx, lmac_idx ); - - /* Set MAC address */ - txnic_bgx_mac ( lmac ); - - /* Initialise PHY */ - txnic_bgx_spu_init ( lmac ); - - /* Accept all multicasts and broadcasts */ - writeq ( ( BGX_CMR_RX_DMAC_CTL_MCST_MODE_ACCEPT | - BGX_CMR_RX_DMAC_CTL_BCST_ACCEPT ), - ( lmac->regs + BGX_CMR_RX_DMAC_CTL ) ); - - /* Enable LMAC */ - config = readq ( lmac->regs + BGX_CMR_CONFIG ); - config |= ( BGX_CMR_CONFIG_ENABLE | - BGX_CMR_CONFIG_DATA_PKT_RX_EN | - BGX_CMR_CONFIG_DATA_PKT_TX_EN ); - writeq ( config, ( lmac->regs + BGX_CMR_CONFIG ) ); -} - -/** - * Probe PCI device - * - * @v pci PCI device - * @ret rc Return status code - */ -static int txnic_bgx_probe ( struct pci_device *pci ) { - struct txnic_bgx *bgx; - struct txnic_pf *pf; - unsigned long membase; - unsigned int i; - int type; - int rc; - - /* Allocate and initialise structure */ - bgx = zalloc ( sizeof ( *bgx ) ); - if ( ! bgx ) { - rc = -ENOMEM; - goto err_alloc; - } - bgx->pci = pci; - pci_set_drvdata ( pci, bgx ); - - /* Get base address */ - membase = pciea_bar_start ( pci, PCIEA_BEI_BAR_0 ); - - /* Calculate node ID and index */ - bgx->node = txnic_address_node ( membase ); - bgx->idx = txnic_address_bgx ( membase ); - - /* Fix up PCI device */ - adjust_pci_device ( pci ); - - /* Map registers */ - bgx->regs = ioremap ( membase, TXNIC_BGX_BAR_SIZE ); - if ( ! bgx->regs ) { - rc = -ENODEV; - goto err_ioremap; - } - - /* Detect LMAC type */ - if ( ( type = txnic_bgx_detect ( bgx ) ) < 0 ) { - rc = type; - goto err_detect; - } - DBGC ( TXNICCOL ( bgx ), "TXNIC %d/%d/* BGX %s at %#lx %dx %s%s\n", - bgx->node, bgx->idx, pci->dev.name, membase, bgx->count, - bgx->type->name, ( bgx->training ? "(training)" : "" ) ); - - /* Initialise interface */ - txnic_bgx_init ( bgx, type ); - - /* Initialise all LMACs */ - for ( i = 0 ; i < bgx->count ; i++ ) - txnic_bgx_lmac_init ( bgx, i ); - - /* Add to list of BGX devices */ - list_add_tail ( &bgx->list, &txnic_bgxs ); - - /* Probe all LMACs, if applicable */ - list_for_each_entry ( pf, &txnic_pfs, list ) { - if ( pf->node != bgx->node ) - continue; - if ( ( rc = txnic_lmac_probe_all ( pf, bgx ) ) != 0 ) - goto err_probe; - } - - return 0; - - if ( bgx->pf ) - txnic_lmac_remove_all ( bgx->pf, bgx ); - list_del ( &bgx->list ); - err_probe: - err_detect: - iounmap ( bgx->regs ); - err_ioremap: - free ( bgx ); - err_alloc: - return rc; -} - -/** - * Remove PCI device - * - * @v pci PCI device - */ -static void txnic_bgx_remove ( struct pci_device *pci ) { - struct txnic_bgx *bgx = pci_get_drvdata ( pci ); - - /* Remove all LMACs, if applicable */ - if ( bgx->pf ) - txnic_lmac_remove_all ( bgx->pf, bgx ); - - /* Remove from list of BGX devices */ - list_del ( &bgx->list ); - - /* Unmap registers */ - iounmap ( bgx->regs ); - - /* Free BGX device */ - free ( bgx ); -} - -/** BGX PCI device IDs */ -static struct pci_device_id txnic_bgx_ids[] = { - PCI_ROM ( 0x177d, 0xa026, "thunder-bgx", "ThunderX BGX", 0 ), -}; - -/** BGX PCI driver */ -struct pci_driver txnic_bgx_driver __pci_driver = { - .ids = txnic_bgx_ids, - .id_count = ( sizeof ( txnic_bgx_ids ) / sizeof ( txnic_bgx_ids[0] ) ), - .probe = txnic_bgx_probe, - .remove = txnic_bgx_remove, -}; diff --git a/roms/ipxe/src/drivers/net/thunderx.h b/roms/ipxe/src/drivers/net/thunderx.h deleted file mode 100644 index 410daf6e2..000000000 --- a/roms/ipxe/src/drivers/net/thunderx.h +++ /dev/null @@ -1,949 +0,0 @@ -#ifndef _THUNDERX_H -#define _THUNDERX_H - -/** @file - * - * Cavium ThunderX Ethernet driver - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdint.h> -#include <ipxe/list.h> -#include <ipxe/netdevice.h> -#include <ipxe/uaccess.h> - -/****************************************************************************** - * - * Address space - * - ****************************************************************************** - */ - -/** Size of a cache line */ -#define TXNIC_LINE_SIZE 128 - -/** Virtual function BAR size */ -#define TXNIC_VF_BAR_SIZE 0x200000UL - -/** Physical function BAR size */ -#define TXNIC_PF_BAR_SIZE 0x40000000UL - -/** BGX BAR size */ -#define TXNIC_BGX_BAR_SIZE 0x400000UL - -/** Maximum number of BGX Ethernet interfaces (per node) */ -#define TXNIC_NUM_BGX 2 - -/** Maximum number of Logical MACs (per BGX) */ -#define TXNIC_NUM_LMAC 4 - -/** Maximum number of destination MAC addresses (per BGX) */ -#define TXNIC_NUM_DMAC 32 - -/** Maximum number of steering rules (per BGX) */ -#define TXNIC_NUM_STEERING 8 - -/** - * Calculate node ID - * - * @v addr PCI BAR base address - * @ret node Node ID - */ -static inline unsigned int txnic_address_node ( uint64_t addr ) { - - /* Node ID is in bits [45:44] of the hardcoded BAR address */ - return ( ( addr >> 44 ) & 0x3 ); -} - -/** - * Calculate BGX Ethernet interface index - * - * @v addr PCI BAR base address - * @ret index Index - */ -static inline unsigned int txnic_address_bgx ( uint64_t addr ) { - - /* Index is in bit 24 of the hardcoded BAR address */ - return ( ( addr >> 24 ) & 0x1 ); -} - -/****************************************************************************** - * - * Send queue - * - ****************************************************************************** - */ - -/** Send queue configuration */ -#define TXNIC_QS_SQ_CFG(q) ( ( (q) << 18 ) | 0x010800 ) -#define TXNIC_QS_SQ_CFG_ENA ( 1ULL << 19 ) -#define TXNIC_QS_SQ_CFG_RESET ( 1ULL << 17 ) -#define TXNIC_QS_SQ_CFG_QSIZE(sz) ( ( ( uint64_t ) (sz) ) << 8 ) -#define TXNIC_QS_SQ_CFG_QSIZE_1K \ - TXNIC_QS_SQ_CFG_QSIZE ( 0 ) - -/** Send queue base address */ -#define TXNIC_QS_SQ_BASE(q) ( ( (q) << 18 ) | 0x010820 ) - -/** Send queue head pointer */ -#define TXNIC_QS_SQ_HEAD(q) ( ( (q) << 18 ) | 0x010828 ) - -/** Send queue tail pointer */ -#define TXNIC_QS_SQ_TAIL(q) ( ( (q) << 18 ) | 0x010830 ) - -/** Send queue doorbell */ -#define TXNIC_QS_SQ_DOOR(q) ( ( (q) << 18 ) | 0x010838 ) - -/** Send queue status */ -#define TXNIC_QS_SQ_STATUS(q) ( ( (q) << 18 ) | 0x010840 ) -#define TXNIC_QS_SQ_STATUS_STOPPED ( 1ULL << 21 ) - -/** Maximum time to wait for a send queue to stop - * - * This is a policy decision. - */ -#define TXNIC_SQ_STOP_MAX_WAIT_MS 100 - -/** A send header subdescriptor */ -struct txnic_send_header { - /** Total length */ - uint32_t total; - /** Unused */ - uint8_t unused_a[2]; - /** Subdescriptor count */ - uint8_t subdcnt; - /** Flags */ - uint8_t flags; - /** Unused */ - uint8_t unused_b[8]; -} __attribute__ (( packed )); - -/** Flags for send header subdescriptor - * - * These comprise SUBDC=0x1 and PNC=0x1. - */ -#define TXNIC_SEND_HDR_FLAGS 0x14 - -/** A send gather subdescriptor */ -struct txnic_send_gather { - /** Size */ - uint16_t size; - /** Unused */ - uint8_t unused[5]; - /** Flags */ - uint8_t flags; - /** Address */ - uint64_t addr; -} __attribute__ (( packed )); - -/** Flags for send gather subdescriptor - * - * These comprise SUBDC=0x4 and LD_TYPE=0x0. - */ -#define TXNIC_SEND_GATHER_FLAGS 0x40 - -/** A send queue entry - * - * Each send queue entry comprises a single send header subdescriptor - * and a single send gather subdescriptor. - */ -struct txnic_sqe { - /** Send header descriptor */ - struct txnic_send_header hdr; - /** Send gather descriptor */ - struct txnic_send_gather gather; -} __attribute__ (( packed )); - -/** Number of subdescriptors per send queue entry */ -#define TXNIC_SQE_SUBDESCS ( sizeof ( struct txnic_sqe ) / \ - sizeof ( struct txnic_send_header ) ) - -/** Number of send queue entries - * - * The minimum send queue size is 1024 entries. - */ -#define TXNIC_SQES ( 1024 / TXNIC_SQE_SUBDESCS ) - -/** Send queue maximum fill level - * - * This is a policy decision. - */ -#define TXNIC_SQ_FILL 32 - -/** Send queue alignment */ -#define TXNIC_SQ_ALIGN TXNIC_LINE_SIZE - -/** Send queue stride */ -#define TXNIC_SQ_STRIDE sizeof ( struct txnic_sqe ) - -/** Send queue size */ -#define TXNIC_SQ_SIZE ( TXNIC_SQES * TXNIC_SQ_STRIDE ) - -/** A send queue */ -struct txnic_sq { - /** Producer counter */ - unsigned int prod; - /** Consumer counter */ - unsigned int cons; - /** Send queue entries */ - userptr_t sqe; -}; - -/****************************************************************************** - * - * Receive queue - * - ****************************************************************************** - */ - -/** Receive queue configuration */ -#define TXNIC_QS_RQ_CFG(q) ( ( (q) << 18 ) | 0x010600 ) -#define TXNIC_QS_RQ_CFG_ENA ( 1ULL << 1 ) - -/** Maximum time to wait for a receive queue to disable - * - * This is a policy decision. - */ -#define TXNIC_RQ_DISABLE_MAX_WAIT_MS 100 - -/** Receive buffer descriptor ring configuration */ -#define TXNIC_QS_RBDR_CFG(q) ( ( (q) << 18 ) | 0x010c00 ) -#define TXNIC_QS_RBDR_CFG_ENA ( 1ULL << 44 ) -#define TXNIC_QS_RBDR_CFG_RESET ( 1ULL << 43 ) -#define TXNIC_QS_RBDR_CFG_QSIZE(sz) ( ( ( uint64_t ) (sz) ) << 32 ) -#define TXNIC_QS_RBDR_CFG_QSIZE_8K \ - TXNIC_QS_RBDR_CFG_QSIZE ( 0 ) -#define TXNIC_QS_RBDR_CFG_LINES(sz) ( ( ( uint64_t ) (sz) ) << 0 ) - -/** Receive buffer descriptor ring base address */ -#define TXNIC_QS_RBDR_BASE(q) ( ( (q) << 18 ) | 0x010c20 ) - -/** Receive buffer descriptor ring head pointer */ -#define TXNIC_QS_RBDR_HEAD(q) ( ( (q) << 18 ) | 0x010c28 ) - -/** Receive buffer descriptor ring tail pointer */ -#define TXNIC_QS_RBDR_TAIL(q) ( ( (q) << 18 ) | 0x010c30 ) - -/** Receive buffer descriptor ring doorbell */ -#define TXNIC_QS_RBDR_DOOR(q) ( ( (q) << 18 ) | 0x010c38 ) - -/** Receive buffer descriptor ring status 0 */ -#define TXNIC_QS_RBDR_STATUS0(q) ( ( (q) << 18 ) | 0x010c40 ) - -/** A receive buffer descriptor ring entry */ -struct txnic_rbdr_entry { - /** Address */ - uint64_t addr; -} __attribute__ (( packed )); - -/** A receive queue entry */ -struct txnic_rqe { - /** Receive buffer descriptor ring entry */ - struct txnic_rbdr_entry rbdre; -} __attribute__ (( packed )); - -/** Number of receive queue entries - * - * The minimum receive queue size is 8192 entries. - */ -#define TXNIC_RQES 8192 - -/** Receive queue maximum fill level - * - * This is a policy decision. Must not exceed TXNIC_RQES. - */ -#define TXNIC_RQ_FILL 32 - -/** Receive queue entry size - * - * This is a policy decision. - */ -#define TXNIC_RQE_SIZE ( ( ETH_DATA_ALIGN + ETH_FRAME_LEN + \ - 4 /* VLAN */ + TXNIC_LINE_SIZE - 1 ) \ - & ~( TXNIC_LINE_SIZE - 1 ) ) - -/** Receive queue alignment */ -#define TXNIC_RQ_ALIGN TXNIC_LINE_SIZE - -/** Receive queue stride */ -#define TXNIC_RQ_STRIDE sizeof ( struct txnic_rqe ) - -/** Receive queue size */ -#define TXNIC_RQ_SIZE ( TXNIC_RQES * TXNIC_RQ_STRIDE ) - -/** A receive queue */ -struct txnic_rq { - /** Producer counter */ - unsigned int prod; - /** Consumer counter */ - unsigned int cons; - /** Receive queue entries */ - userptr_t rqe; - /** I/O buffers */ - struct io_buffer *iobuf[TXNIC_RQ_FILL]; -}; - -/****************************************************************************** - * - * Completion queue - * - ****************************************************************************** - */ - -/** Completion queue configuration */ -#define TXNIC_QS_CQ_CFG(q) ( ( (q) << 18 ) | 0x010400 ) -#define TXNIC_QS_CQ_CFG_ENA ( 1ULL << 42 ) -#define TXNIC_QS_CQ_CFG_RESET ( 1ULL << 41 ) -#define TXNIC_QS_CQ_CFG_QSIZE(sz) ( ( ( uint64_t ) (sz) ) << 32 ) -#define TXNIC_QS_CQ_CFG_QSIZE_256 \ - TXNIC_QS_CQ_CFG_QSIZE ( 7 ) - -/** Maximum time to wait for a completion queue to disable - * - * This is a policy decision. - */ -#define TXNIC_CQ_DISABLE_MAX_WAIT_MS 100 - -/** Completion queue base address */ -#define TXNIC_QS_CQ_BASE(q) ( ( (q) << 18 ) | 0x010420 ) - -/** Completion queue head pointer */ -#define TXNIC_QS_CQ_HEAD(q) ( ( (q) << 18 ) | 0x010428 ) - -/** Completion queue tail pointer */ -#define TXNIC_QS_CQ_TAIL(q) ( ( (q) << 18 ) | 0x010430 ) - -/** Completion queue doorbell */ -#define TXNIC_QS_CQ_DOOR(q) ( ( (q) << 18 ) | 0x010438 ) - -/** Completion queue status */ -#define TXNIC_QS_CQ_STATUS(q) ( ( (q) << 18 ) | 0x010440 ) -#define TXNIC_QS_CQ_STATUS_QCOUNT(status) \ - ( ( (status) >> 0 ) & 0xffff ) - -/** Completion queue status 2 */ -#define TXNIC_QS_CQ_STATUS2(q) ( ( (q) << 18 ) | 0x010448 ) - -/** A send completion queue entry */ -struct txnic_cqe_send { - /** Status */ - uint8_t send_status; - /** Unused */ - uint8_t unused[4]; - /** Send queue entry pointer */ - uint16_t sqe_ptr; - /** Type */ - uint8_t cqe_type; -} __attribute__ (( packed )); - -/** Send completion queue entry type */ -#define TXNIC_CQE_TYPE_SEND 0x80 - -/** A receive completion queue entry */ -struct txnic_cqe_rx { - /** Error opcode */ - uint8_t errop; - /** Unused */ - uint8_t unused_a[6]; - /** Type */ - uint8_t cqe_type; - /** Unused */ - uint8_t unused_b[1]; - /** Padding */ - uint8_t apad; - /** Unused */ - uint8_t unused_c[4]; - /** Length */ - uint16_t len; -} __attribute__ (( packed )); - -/** Receive completion queue entry type */ -#define TXNIC_CQE_TYPE_RX 0x20 - -/** Applied padding */ -#define TXNIC_CQE_RX_APAD_LEN( apad ) ( (apad) >> 5 ) - -/** Completion queue entry common fields */ -struct txnic_cqe_common { - /** Unused */ - uint8_t unused_a[7]; - /** Type */ - uint8_t cqe_type; -} __attribute__ (( packed )); - -/** A completion queue entry */ -union txnic_cqe { - /** Common fields */ - struct txnic_cqe_common common; - /** Send completion */ - struct txnic_cqe_send send; - /** Receive completion */ - struct txnic_cqe_rx rx; -}; - -/** Number of completion queue entries - * - * The minimum completion queue size is 256 entries. - */ -#define TXNIC_CQES 256 - -/** Completion queue alignment */ -#define TXNIC_CQ_ALIGN 512 - -/** Completion queue stride */ -#define TXNIC_CQ_STRIDE 512 - -/** Completion queue size */ -#define TXNIC_CQ_SIZE ( TXNIC_CQES * TXNIC_CQ_STRIDE ) - -/** A completion queue */ -struct txnic_cq { - /** Consumer counter */ - unsigned int cons; - /** Completion queue entries */ - userptr_t cqe; -}; - -/****************************************************************************** - * - * Virtual NIC - * - ****************************************************************************** - */ - -/** A virtual NIC */ -struct txnic { - /** Registers */ - void *regs; - /** Device name (for debugging) */ - const char *name; - /** Network device */ - struct net_device *netdev; - - /** Send queue */ - struct txnic_sq sq; - /** Receive queue */ - struct txnic_rq rq; - /** Completion queue */ - struct txnic_cq cq; -}; - -/****************************************************************************** - * - * Physical function - * - ****************************************************************************** - */ - -/** Physical function configuration */ -#define TXNIC_PF_CFG 0x000000 -#define TXNIC_PF_CFG_ENA ( 1ULL << 0 ) - -/** Backpressure configuration */ -#define TXNIC_PF_BP_CFG 0x000080 -#define TXNIC_PF_BP_CFG_BP_POLL_ENA ( 1ULL << 6 ) -#define TXNIC_PF_BP_CFG_BP_POLL_DLY(dl) ( ( ( uint64_t ) (dl) ) << 0 ) -#define TXNIC_PF_BP_CFG_BP_POLL_DLY_DEFAULT \ - TXNIC_PF_BP_CFG_BP_POLL_DLY ( 3 ) - -/** Interface send configuration */ -#define TXNIC_PF_INTF_SEND_CFG(in) ( ( (in) << 8 ) | 0x000200 ) -#define TXNIC_PF_INTF_SEND_CFG_BLOCK_BGX ( 1ULL << 3 ) -#define TXNIC_PF_INTF_SEND_CFG_BLOCK(bl) ( ( ( uint64_t ) (bl) ) << 0 ) - -/** Interface backpressure configuration */ -#define TXNIC_PF_INTF_BP_CFG(in) ( ( (in) << 8 ) | 0x000208 ) -#define TXNIC_PF_INTF_BP_CFG_BP_ENA ( 1ULL << 63 ) -#define TXNIC_PF_INTF_BP_CFG_BP_ID_BGX ( 1ULL << 3 ) -#define TXNIC_PF_INTF_BP_CFG_BP_ID(bp) ( ( ( uint64_t ) (bp) ) << 0 ) - -/** Port kind configuration */ -#define TXNIC_PF_PKIND_CFG(pk) ( ( (pk) << 3 ) | 0x000600 ) -#define TXNIC_PF_PKIND_CFG_LENERR_EN ( 1ULL << 33 ) -#define TXNIC_PF_PKIND_CFG_MAXLEN(ct) ( ( ( uint64_t ) (ct) ) << 16 ) -#define TXNIC_PF_PKIND_CFG_MAXLEN_DISABLE \ - TXNIC_PF_PKIND_CFG_MAXLEN ( 0xffff ) -#define TXNIC_PF_PKIND_CFG_MINLEN(ct) ( ( ( uint64_t ) (ct) ) << 0 ) -#define TXNIC_PF_PKIND_CFG_MINLEN_DISABLE \ - TXNIC_PF_PKIND_CFG_MINLEN ( 0x0000 ) - -/** Match parse index configuration */ -#define TXNIC_PF_MPI_CFG(ix) ( ( (ix) << 3 ) | 0x210000 ) -#define TXNIC_PF_MPI_CFG_VNIC(vn) ( ( ( uint64_t ) (vn) ) << 24 ) -#define TXNIC_PF_MPI_CFG_RSSI_BASE(ix) ( ( ( uint64_t ) (ix) ) << 0 ) - -/** RSS indirection receive queue */ -#define TXNIC_PF_RSSI_RQ(ix) ( ( (ix) << 3 ) | 0x220000 ) -#define TXNIC_PF_RSSI_RQ_RQ_QS(qs) ( ( ( uint64_t ) (qs) ) << 3 ) - -/** LMAC registers */ -#define TXNIC_PF_LMAC(lm) ( ( (lm) << 3 ) | 0x240000 ) - -/** LMAC configuration */ -#define TXNIC_PF_LMAC_CFG 0x000000 -#define TXNIC_PF_LMAC_CFG_ADJUST(ad) ( ( ( uint64_t ) (ad) ) << 8 ) -#define TXNIC_PF_LMAC_CFG_ADJUST_DEFAULT \ - TXNIC_PF_LMAC_CFG_ADJUST ( 6 ) -#define TXNIC_PF_LMAC_CFG_MIN_PKT_SIZE(sz) ( ( ( uint64_t ) (sz) ) << 0 ) - -/** LMAC configuration 2 */ -#define TXNIC_PF_LMAC_CFG2 0x000100 -#define TXNIC_PF_LMAC_CFG2_MAX_PKT_SIZE(sz) ( ( ( uint64_t ) (sz) ) << 0 ) - -/** LMAC credit */ -#define TXNIC_PF_LMAC_CREDIT 0x004000 -#define TXNIC_PF_LMAC_CREDIT_CC_UNIT_CNT(ct) ( ( ( uint64_t ) (ct) ) << 12 ) -#define TXNIC_PF_LMAC_CREDIT_CC_UNIT_CNT_DEFAULT \ - TXNIC_PF_LMAC_CREDIT_CC_UNIT_CNT ( 192 ) -#define TXNIC_PF_LMAC_CREDIT_CC_PACKET_CNT(ct) ( ( ( uint64_t ) (ct) ) << 2 ) -#define TXNIC_PF_LMAC_CREDIT_CC_PACKET_CNT_DEFAULT \ - TXNIC_PF_LMAC_CREDIT_CC_PACKET_CNT ( 511 ) -#define TXNIC_PF_LMAC_CREDIT_CC_ENABLE ( 1ULL << 1 ) - -/** Channel registers */ -#define TXNIC_PF_CHAN(ch) ( ( (ch) << 3 ) | 0x400000 ) - -/** Channel transmit configuration */ -#define TXNIC_PF_CHAN_TX_CFG 0x000000 -#define TXNIC_PF_CHAN_TX_CFG_BP_ENA ( 1ULL << 0 ) - -/** Channel receive configuration */ -#define TXNIC_PF_CHAN_RX_CFG 0x020000 -#define TXNIC_PF_CHAN_RX_CFG_CPI_BASE(ix) ( ( ( uint64_t ) (ix) ) << 48 ) - -/** Channel receive backpressure configuration */ -#define TXNIC_PF_CHAN_RX_BP_CFG 0x080000 -#define TXNIC_PF_CHAN_RX_BP_CFG_ENA ( 1ULL << 63 ) -#define TXNIC_PF_CHAN_RX_BP_CFG_BPID(bp) ( ( ( uint64_t ) (bp) ) << 0 ) - -/** Traffic limiter 2 configuration */ -#define TXNIC_PF_TL2_CFG(tl) ( ( (tl) << 3 ) | 0x500000 ) -#define TXNIC_PF_TL2_CFG_RR_QUANTUM(rr) ( ( ( uint64_t ) (rr) ) << 0 ) -#define TXNIC_PF_TL2_CFG_RR_QUANTUM_DEFAULT \ - TXNIC_PF_TL2_CFG_RR_QUANTUM ( 0x905 ) - -/** Traffic limiter 3 configuration */ -#define TXNIC_PF_TL3_CFG(tl) ( ( (tl) << 3 ) | 0x600000 ) -#define TXNIC_PF_TL3_CFG_RR_QUANTUM(rr) ( ( ( uint64_t ) (rr) ) << 0 ) -#define TXNIC_PF_TL3_CFG_RR_QUANTUM_DEFAULT \ - TXNIC_PF_TL3_CFG_RR_QUANTUM ( 0x905 ) - -/** Traffic limiter 3 channel mapping */ -#define TXNIC_PF_TL3_CHAN(tl) ( ( (tl) << 3 ) | 0x620000 ) -#define TXNIC_PF_TL3_CHAN_CHAN(ch) ( ( (ch) & 0x7f ) << 0 ) - -/** Traffic limiter 4 configuration */ -#define TXNIC_PF_TL4_CFG(tl) ( ( (tl) << 3 ) | 0x800000 ) -#define TXNIC_PF_TL4_CFG_SQ_QS(qs) ( ( ( uint64_t ) (qs) ) << 27 ) -#define TXNIC_PF_TL4_CFG_RR_QUANTUM(rr) ( ( ( uint64_t ) (rr) ) << 0 ) -#define TXNIC_PF_TL4_CFG_RR_QUANTUM_DEFAULT \ - TXNIC_PF_TL4_CFG_RR_QUANTUM ( 0x905 ) - -/** Queue set registers */ -#define TXNIC_PF_QS(qs) ( ( (qs) << 21 ) | 0x20000000UL ) - -/** Queue set configuration */ -#define TXNIC_PF_QS_CFG 0x010000 -#define TXNIC_PF_QS_CFG_ENA ( 1ULL << 31 ) -#define TXNIC_PF_QS_CFG_VNIC(vn) ( ( ( uint64_t ) (vn) ) << 0 ) - -/** Receive queue configuration */ -#define TXNIC_PF_QS_RQ_CFG(q) ( ( (q) << 18 ) | 0x010400 ) -#define TXNIC_PF_QS_RQ_CFG_CACHING(cx) ( ( ( uint64_t ) (cx) ) << 26 ) -#define TXNIC_PF_QS_RQ_CFG_CACHING_ALL \ - TXNIC_PF_QS_RQ_CFG_CACHING ( 1 ) -#define TXNIC_PF_QS_RQ_CFG_CQ_QS(qs) ( ( ( uint64_t ) (qs) ) << 19 ) -#define TXNIC_PF_QS_RQ_CFG_RBDR_CONT_QS(qs) ( ( ( uint64_t ) (qs) ) << 9 ) -#define TXNIC_PF_QS_RQ_CFG_RBDR_STRT_QS(qs) ( ( ( uint64_t ) (qs) ) << 1 ) - -/** Receive queue drop configuration */ -#define TXNIC_PF_QS_RQ_DROP_CFG(q) ( ( (q) << 18 ) | 0x010420 ) - -/** Receive queue backpressure configuration */ -#define TXNIC_PF_QS_RQ_BP_CFG(q) ( ( (q) << 18 ) | 0x010500 ) -#define TXNIC_PF_QS_RQ_BP_CFG_RBDR_BP_ENA ( 1ULL << 63 ) -#define TXNIC_PF_QS_RQ_BP_CFG_CQ_BP_ENA ( 1ULL << 62 ) -#define TXNIC_PF_QS_RQ_BP_CFG_BPID(bp) ( ( ( uint64_t ) (bp) ) << 0 ) - -/** Send queue configuration */ -#define TXNIC_PF_QS_SQ_CFG(q) ( ( (q) << 18 ) | 0x010c00 ) -#define TXNIC_PF_QS_SQ_CFG_CQ_QS(qs) ( ( ( uint64_t ) (qs) ) << 3 ) - -/** Send queue configuration 2 */ -#define TXNIC_PF_QS_SQ_CFG2(q) ( ( (q) << 18 ) | 0x010c08 ) -#define TXNIC_PF_QS_SQ_CFG2_TL4(tl) ( ( ( uint64_t ) (tl) ) << 0 ) - -/** A physical function */ -struct txnic_pf { - /** Registers */ - void *regs; - /** PCI device */ - struct pci_device *pci; - /** Node ID */ - unsigned int node; - - /** Virtual function BAR base */ - unsigned long vf_membase; - /** Virtual function BAR stride */ - unsigned long vf_stride; - - /** List of physical functions */ - struct list_head list; - /** BGX Ethernet interfaces (if known) */ - struct txnic_bgx *bgx[TXNIC_NUM_BGX]; -}; - -/** - * Calculate virtual NIC index - * - * @v bgx_idx BGX Ethernet interface index - * @v lmac_idx Logical MAC index - * @ret vnic_idx Virtual NIC index - */ -#define TXNIC_VNIC_IDX( bgx_idx, lmac_idx ) \ - ( ( (bgx_idx) * TXNIC_NUM_LMAC ) + (lmac_idx) ) - -/** - * Calculate BGX Ethernet interface index - * - * @v vnic_idx Virtual NIC index - * @ret bgx_idx BGX Ethernet interface index - */ -#define TXNIC_BGX_IDX( vnic_idx ) ( (vnic_idx) / TXNIC_NUM_LMAC ) - -/** - * Calculate logical MAC index - * - * @v vnic_idx Virtual NIC index - * @ret lmac_idx Logical MAC index - */ -#define TXNIC_LMAC_IDX( vnic_idx ) ( (vnic_idx) % TXNIC_NUM_LMAC ) - -/** - * Calculate traffic limiter 2 index - * - * @v vnic_idx Virtual NIC index - * @v tl2_idx Traffic limiter 2 index - */ -#define TXNIC_TL2_IDX( vnic_idx ) ( (vnic_idx) << 3 ) - -/** - * Calculate traffic limiter 3 index - * - * @v vnic_idx Virtual NIC index - * @v tl3_idx Traffic limiter 3 index - */ -#define TXNIC_TL3_IDX( vnic_idx ) ( (vnic_idx) << 5 ) - -/** - * Calculate traffic limiter 4 index - * - * @v vnic_idx Virtual NIC index - * @v tl4_idx Traffic limiter 4 index - */ -#define TXNIC_TL4_IDX( vnic_idx ) ( (vnic_idx) << 7 ) - -/** - * Calculate channel index - * - * @v vnic_idx Virtual NIC index - * @v chan_idx Channel index - */ -#define TXNIC_CHAN_IDX( vnic_idx ) ( ( TXNIC_BGX_IDX (vnic_idx) << 7 ) | \ - ( TXNIC_LMAC_IDX (vnic_idx) << 4 ) ) - -/****************************************************************************** - * - * BGX Ethernet interface - * - ****************************************************************************** - */ - -/** Per-LMAC registers */ -#define BGX_LMAC(lm) ( ( (lm) << 20 ) | 0x00000000UL ) - -/** CMR configuration */ -#define BGX_CMR_CONFIG 0x000000 -#define BGX_CMR_CONFIG_ENABLE ( 1ULL << 15 ) -#define BGX_CMR_CONFIG_DATA_PKT_RX_EN ( 1ULL << 14 ) -#define BGX_CMR_CONFIG_DATA_PKT_TX_EN ( 1ULL << 13 ) -#define BGX_CMR_CONFIG_LMAC_TYPE_GET(config) \ - ( ( (config) >> 8 ) & 0x7 ) -#define BGX_CMR_CONFIG_LMAC_TYPE_SET(ty) ( ( ( uint64_t ) (ty) ) << 8 ) -#define BGX_CMR_CONFIG_LANE_TO_SDS(ls) ( ( ( uint64_t ) (ls) ) << 0 ) - -/** CMR global configuration */ -#define BGX_CMR_GLOBAL_CONFIG 0x000008 -#define BGX_CMR_GLOBAL_CONFIG_FCS_STRIP ( 1ULL << 6 ) - -/** CMR receive statistics 0 */ -#define BGX_CMR_RX_STAT0 0x000070 - -/** CMR receive statistics 1 */ -#define BGX_CMR_RX_STAT1 0x000078 - -/** CMR receive statistics 2 */ -#define BGX_CMR_RX_STAT2 0x000080 - -/** CMR receive statistics 3 */ -#define BGX_CMR_RX_STAT3 0x000088 - -/** CMR receive statistics 4 */ -#define BGX_CMR_RX_STAT4 0x000090 - -/** CMR receive statistics 5 */ -#define BGX_CMR_RX_STAT5 0x000098 - -/** CMR receive statistics 6 */ -#define BGX_CMR_RX_STAT6 0x0000a0 - -/** CMR receive statistics 7 */ -#define BGX_CMR_RX_STAT7 0x0000a8 - -/** CMR receive statistics 8 */ -#define BGX_CMR_RX_STAT8 0x0000b0 - -/** CMR receive statistics 9 */ -#define BGX_CMR_RX_STAT9 0x0000b8 - -/** CMR receive statistics 10 */ -#define BGX_CMR_RX_STAT10 0x0000c0 - -/** CMR destination MAC control */ -#define BGX_CMR_RX_DMAC_CTL 0x0000e8 -#define BGX_CMR_RX_DMAC_CTL_MCST_MODE(md) ( ( ( uint64_t ) (md) ) << 1 ) -#define BGX_CMR_RX_DMAC_CTL_MCST_MODE_ACCEPT \ - BGX_CMR_RX_DMAC_CTL_MCST_MODE ( 1 ) -#define BGX_CMR_RX_DMAC_CTL_BCST_ACCEPT ( 1ULL << 0 ) - -/** CMR destination MAC CAM */ -#define BGX_CMR_RX_DMAC_CAM(i) ( ( (i) << 3 ) | 0x000200 ) - -/** CMR receive steering */ -#define BGX_CMR_RX_STEERING(i) ( ( (i) << 3 ) | 0x000300 ) - -/** CMR backpressure channel mask AND */ -#define BGX_CMR_CHAN_MSK_AND 0x000450 -#define BGX_CMR_CHAN_MSK_AND_ALL(count) \ - ( 0xffffffffffffffffULL >> ( 16 * ( 4 - (count) ) ) ) - -/** CMR transmit statistics 0 */ -#define BGX_CMR_TX_STAT0 0x000600 - -/** CMR transmit statistics 1 */ -#define BGX_CMR_TX_STAT1 0x000608 - -/** CMR transmit statistics 2 */ -#define BGX_CMR_TX_STAT2 0x000610 - -/** CMR transmit statistics 3 */ -#define BGX_CMR_TX_STAT3 0x000618 - -/** CMR transmit statistics 4 */ -#define BGX_CMR_TX_STAT4 0x000620 - -/** CMR transmit statistics 5 */ -#define BGX_CMR_TX_STAT5 0x000628 - -/** CMR transmit statistics 6 */ -#define BGX_CMR_TX_STAT6 0x000630 - -/** CMR transmit statistics 7 */ -#define BGX_CMR_TX_STAT7 0x000638 - -/** CMR transmit statistics 8 */ -#define BGX_CMR_TX_STAT8 0x000640 - -/** CMR transmit statistics 9 */ -#define BGX_CMR_TX_STAT9 0x000648 - -/** CMR transmit statistics 10 */ -#define BGX_CMR_TX_STAT10 0x000650 - -/** CMR transmit statistics 11 */ -#define BGX_CMR_TX_STAT11 0x000658 - -/** CMR transmit statistics 12 */ -#define BGX_CMR_TX_STAT12 0x000660 - -/** CMR transmit statistics 13 */ -#define BGX_CMR_TX_STAT13 0x000668 - -/** CMR transmit statistics 14 */ -#define BGX_CMR_TX_STAT14 0x000670 - -/** CMR transmit statistics 15 */ -#define BGX_CMR_TX_STAT15 0x000678 - -/** CMR transmit statistics 16 */ -#define BGX_CMR_TX_STAT16 0x000680 - -/** CMR transmit statistics 17 */ -#define BGX_CMR_TX_STAT17 0x000688 - -/** CMR receive logical MACs */ -#define BGX_CMR_RX_LMACS 0x000468 -#define BGX_CMR_RX_LMACS_LMACS_GET(lmacs) \ - ( ( (lmacs) >> 0 ) & 0x7 ) -#define BGX_CMR_RX_LMACS_LMACS_SET(ct) ( ( ( uint64_t ) (ct) ) << 0 ) - -/** CMR transmit logical MACs */ -#define BGX_CMR_TX_LMACS 0x001000 -#define BGX_CMR_TX_LMACS_LMACS_GET(lmacs) \ - ( ( (lmacs) >> 0 ) & 0x7 ) -#define BGX_CMR_TX_LMACS_LMACS_SET(ct) ( ( ( uint64_t ) (ct) ) << 0 ) - -/** SPU control 1 */ -#define BGX_SPU_CONTROL1 0x010000 -#define BGX_SPU_CONTROL1_RESET ( 1ULL << 15 ) -#define BGX_SPU_CONTROL1_LO_PWR ( 1ULL << 11 ) - -/** SPU reset delay */ -#define BGX_SPU_RESET_DELAY_MS 10 - -/** SPU status 1 */ -#define BGX_SPU_STATUS1 0x010008 -#define BGX_SPU_STATUS1_FLT ( 1ULL << 7 ) -#define BGX_SPU_STATUS1_RCV_LNK ( 1ULL << 2 ) - -/** SPU status 2 */ -#define BGX_SPU_STATUS2 0x010020 -#define BGX_SPU_STATUS2_RCVFLT ( 1ULL << 10 ) - -/** SPU BASE-R status 1 */ -#define BGX_SPU_BR_STATUS1 0x010030 -#define BGX_SPU_BR_STATUS1_RCV_LNK ( 1ULL << 12 ) -#define BGX_SPU_BR_STATUS1_HI_BER ( 1ULL << 1 ) -#define BGX_SPU_BR_STATUS1_BLK_LOCK ( 1ULL << 0 ) - -/** SPU BASE-R status 2 */ -#define BGX_SPU_BR_STATUS2 0x010038 -#define BGX_SPU_BR_STATUS2_LATCHED_LOCK ( 1ULL << 15 ) -#define BGX_SPU_BR_STATUS2_LATCHED_BER ( 1ULL << 14 ) - -/** SPU BASE-R alignment status */ -#define BGX_SPU_BR_ALGN_STATUS 0x010050 -#define BGX_SPU_BR_ALGN_STATUS_ALIGND ( 1ULL << 12 ) - -/** SPU BASE-R link training control */ -#define BGX_SPU_BR_PMD_CONTROL 0x010068 -#define BGX_SPU_BR_PMD_CONTROL_TRAIN_EN ( 1ULL << 1 ) - -/** SPU BASE-R link training status */ -#define BGX_SPU_BR_PMD_STATUS 0x010070 - -/** SPU link partner coefficient update */ -#define BGX_SPU_BR_PMD_LP_CUP 0x010078 - -/** SPU local device coefficient update */ -#define BGX_SPU_BR_PMD_LD_CUP 0x010088 - -/** SPU local device status report */ -#define BGX_SPU_BR_PMD_LD_REP 0x010090 - -/** SPU forward error correction control */ -#define BGX_SPU_FEC_CONTROL 0x0100a0 - -/** SPU autonegotation control */ -#define BGX_SPU_AN_CONTROL 0x0100c8 - -/** SPU autonegotiation status */ -#define BGX_SPU_AN_STATUS 0x0100d0 -#define BGX_SPU_AN_STATUS_XNP_STAT ( 1ULL << 7 ) -#define BGX_SPU_AN_STATUS_PAGE_RX ( 1ULL << 6 ) -#define BGX_SPU_AN_STATUS_AN_COMPLETE ( 1ULL << 5 ) -#define BGX_SPU_AN_STATUS_LINK_STATUS ( 1ULL << 2 ) -#define BGX_SPU_AN_STATUS_LP_AN_ABLE ( 1ULL << 0 ) - -/** SPU interrupt */ -#define BGX_SPU_INT 0x010220 -#define BGX_SPU_INT_TRAINING_FAIL ( 1ULL << 14 ) -#define BGX_SPU_INT_TRAINING_DONE ( 1ULL << 13 ) -#define BGX_SPU_INT_AN_COMPLETE ( 1ULL << 12 ) -#define BGX_SPU_INT_AN_LINK_GOOD ( 1ULL << 11 ) -#define BGX_SPU_INT_AN_PAGE_RX ( 1ULL << 10 ) -#define BGX_SPU_INT_FEC_UNCORR ( 1ULL << 9 ) -#define BGX_SPU_INT_FEC_CORR ( 1ULL << 8 ) -#define BGX_SPU_INT_BIP_ERR ( 1ULL << 7 ) -#define BGX_SPU_INT_DBG_SYNC ( 1ULL << 6 ) -#define BGX_SPU_INT_ALGNLOS ( 1ULL << 5 ) -#define BGX_SPU_INT_SYNLOS ( 1ULL << 4 ) -#define BGX_SPU_INT_BITLCKLS ( 1ULL << 3 ) -#define BGX_SPU_INT_ERR_BLK ( 1ULL << 2 ) -#define BGX_SPU_INT_RX_LINK_DOWN ( 1ULL << 1 ) -#define BGX_SPU_INT_RX_LINK_UP ( 1ULL << 0 ) - -/** LMAC types */ -enum txnic_lmac_types { - TXNIC_LMAC_SGMII = 0x0, /**< SGMII/1000BASE-X */ - TXNIC_LMAC_XAUI = 0x1, /**< 10GBASE-X/XAUI or DXAUI */ - TXNIC_LMAC_RXAUI = 0x2, /**< Reduced XAUI */ - TXNIC_LMAC_10G_R = 0x3, /**< 10GBASE-R */ - TXNIC_LMAC_40G_R = 0x4, /**< 40GBASE-R */ -}; - -/** An LMAC type */ -struct txnic_lmac_type { - /** Name */ - const char *name; - /** Number of LMACs */ - uint8_t count; - /** Lane-to-SDS mapping */ - uint32_t lane_to_sds; -}; - -/** An LMAC address */ -union txnic_lmac_address { - struct { - uint8_t pad[2]; - uint8_t raw[ETH_ALEN]; - } __attribute__ (( packed )); - uint64_t be64; -}; - -/** A Logical MAC (LMAC) */ -struct txnic_lmac { - /** Registers */ - void *regs; - /** Containing BGX Ethernet interface */ - struct txnic_bgx *bgx; - /** Virtual NIC index */ - unsigned int idx; - - /** MAC address */ - union txnic_lmac_address mac; - - /** Virtual NIC (if applicable) */ - struct txnic *vnic; -}; - -/** A BGX Ethernet interface */ -struct txnic_bgx { - /** Registers */ - void *regs; - /** PCI device */ - struct pci_device *pci; - /** Node ID */ - unsigned int node; - /** BGX index */ - unsigned int idx; - - /** LMAC type */ - struct txnic_lmac_type *type; - /** Number of LMACs */ - unsigned int count; - /** Link training is in use */ - int training; - - /** List of BGX Ethernet interfaces */ - struct list_head list; - /** Physical function (if known) */ - struct txnic_pf *pf; - - /** Logical MACs */ - struct txnic_lmac lmac[TXNIC_NUM_LMAC]; -}; - -#endif /* _THUNDERX_H */ diff --git a/roms/ipxe/src/drivers/net/thunderxcfg.h b/roms/ipxe/src/drivers/net/thunderxcfg.h deleted file mode 100644 index 235c54319..000000000 --- a/roms/ipxe/src/drivers/net/thunderxcfg.h +++ /dev/null @@ -1,211 +0,0 @@ -#ifndef _THUNDERXCFG_H -#define _THUNDERXCFG_H - -/** @file - * - * Cavium ThunderX Board Configuration - * - * The definitions in this section are extracted from BSD-licensed - * (but non-public) portions of ThunderPkg. - * - */ - -FILE_LICENCE ( BSD2 ); - -#include <ipxe/efi/efi.h> - -/****************************************************************************** - * - * From ThunderxBoardConfig.h - * - ****************************************************************************** - * - * Header file for Cavium ThunderX Board Configurations - * Copyright (c) 2015, Cavium Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#define MAX_NODES 2 -#define CLUSTER_COUNT 3 -#define CORE_PER_CLUSTER_COUNT 16 -#define CORE_COUNT (CLUSTER_COUNT*CORE_PER_CLUSTER_COUNT) -#define BGX_PER_NODE_COUNT 2 -#define LMAC_PER_BGX_COUNT 4 -#define PEM_PER_NODE_COUNT 6 -#define LMC_PER_NODE_COUNT 4 -#define DIMM_PER_LMC_COUNT 2 - -#define THUNDERX_CPU_ID(node, cluster, core) (((node) << 16) | ((cluster) << 8) | (core)) - -//TODO: Put common type definitions in separate common include file -typedef enum { - BGX_MODE_SGMII, /* 1 lane, 1.250 Gbaud */ - BGX_MODE_XAUI, /* 4 lanes, 3.125 Gbaud */ - BGX_MODE_DXAUI, /* 4 lanes, 6.250 Gbaud */ - BGX_MODE_RXAUI, /* 2 lanes, 6.250 Gbaud */ - BGX_MODE_XFI, /* 1 lane, 10.3125 Gbaud */ - BGX_MODE_XLAUI, /* 4 lanes, 10.3125 Gbaud */ - BGX_MODE_10G_KR,/* 1 lane, 10.3125 Gbaud */ - BGX_MODE_40G_KR,/* 4 lanes, 10.3125 Gbaud */ - BGX_MODE_UNKNOWN -} BGX_MODE_T; - -typedef enum { - EBB8800, - EBB8804, - CRB_1S, - CRB_2S, - ASIANCAT, - GBT_MT60, - INVENTEC_P3E003, - BOARD_MAX -} BOARD_TYPE; - -typedef struct { - BOOLEAN Enabled; - UINT64 LaneToSds; - UINT64 MacAddress; -} LMAC_CFG; - -typedef struct { - BOOLEAN BgxEnabled; - BGX_MODE_T BgxMode; - UINTN LmacCount; //Maximum number of LMAcs - UINT64 BaseAddress; - UINT64 LmacType; - /* Bit mask of QLMs connected to this BGX */ - UINT64 QlmMask; - UINT64 QlmFreq; - BOOLEAN UseTraining; - LMAC_CFG Lmacs[LMAC_PER_BGX_COUNT]; -} BGX_CFG; - -typedef struct { - BOOLEAN PemUsable; -} PEM_CFG; - -typedef struct { - enum { NotPresent, Empty, Available } Status; - UINT8 Type; - UINT8 SubType; - UINT8 Rank; - UINT16 Mfg; - UINTN SizeMb; - UINTN Speed; - CHAR8 Serial[16]; - CHAR8 PartNo[24]; -} DIMM_CFG; - -typedef struct { - DIMM_CFG DimmCfg[DIMM_PER_LMC_COUNT]; -} LMC_CFG; - -typedef struct { - BOOLEAN Core[CORE_COUNT]; - BGX_CFG BgxCfg[BGX_PER_NODE_COUNT]; - PEM_CFG PemCfg[PEM_PER_NODE_COUNT]; - LMC_CFG LmcCfg[LMC_PER_NODE_COUNT]; - UINT64 RamStart; - UINT64 RamReserve; - UINT64 RamSize; - UINTN CPUSpeed; - UINTN CPUVersion; -} NODE_CFG; - -#define MAX_SERIAL 32 -#define MAX_REVISION 32 -typedef struct { - BOARD_TYPE BoardType; - CHAR8 Serial[MAX_SERIAL]; - CHAR8 Revision[MAX_REVISION]; - UINTN NumNodes; - UINTN BmcBootTwsiBus; - UINTN BmcBootTwsiAddr; - UINTN RtcTwsiBus; - UINTN RtcTwsiAddr; - /* IPMI support*/ - UINTN BmcIpmiTwsiBus; - UINTN BmcIpmiTwsiAddr; - NODE_CFG Node[MAX_NODES]; - UINT16 CpuClusterCount; - UINT16 CpuPerClusterCount; - UINT16 PcieSegmentCount; - UINT64 MacAddrRangeStart; - UINTN DdrSpeed; - UINT64 AcpiOemTableId; -} BOARD_CFG; - -/****************************************************************************** - * - * From ThunderConfigProtocol.h - * - ****************************************************************************** - * - * Thunder board Configuration Protocol - * - * Copyright (c) 2015, Cavium Inc. All rights reserved.<BR> - * - * This program and the accompanying materials are licensed and made - * available under the terms and conditions of the BSD License which - * accompanies this distribution. The full text of the license may - * be found at http://opensource.org/licenses/bsd-license.php - * - * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" - * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER - * EXPRESS OR IMPLIED. - * - */ - -#define EFI_THUNDER_CONFIG_PROTOCOL_GUID \ - {0xb75a0608, 0x99ff, 0x11e5, {0x9b, 0xeb, 0x00, 0x14, 0xd1, 0xfa, 0x23, 0x5c}} - -/// -/// Forward declaration -/// -typedef struct _EFI_THUNDER_CONFIG_PROTOCOL EFI_THUNDER_CONFIG_PROTOCOL; - -/// -/// Function prototypes -/// -typedef -EFI_STATUS -(EFIAPI *EFI_THUNDER_CONFIG_PROTOCOL_GET_CONFIG)( - IN EFI_THUNDER_CONFIG_PROTOCOL *This, - OUT BOARD_CFG** cfg - ); - -/// -/// Protocol structure -/// -struct _EFI_THUNDER_CONFIG_PROTOCOL { - EFI_THUNDER_CONFIG_PROTOCOL_GET_CONFIG GetConfig; - BOARD_CFG* BoardConfig; -}; - -#endif /* _THUNDERXCFG_H */ diff --git a/roms/ipxe/src/drivers/net/virtio-net.c b/roms/ipxe/src/drivers/net/virtio-net.c index fe0fd4b86..533ccb0c6 100644 --- a/roms/ipxe/src/drivers/net/virtio-net.c +++ b/roms/ipxe/src/drivers/net/virtio-net.c @@ -24,15 +24,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <errno.h> #include <stdlib.h> -#include <unistd.h> #include <ipxe/list.h> #include <ipxe/iobuf.h> #include <ipxe/netdevice.h> #include <ipxe/pci.h> #include <ipxe/if_ether.h> #include <ipxe/ethernet.h> -#include <ipxe/virtio-pci.h> #include <ipxe/virtio-ring.h> +#include <ipxe/virtio-pci.h> #include "virtio-net.h" /* @@ -89,12 +88,6 @@ struct virtnet_nic { /** Base pio register address */ unsigned long ioaddr; - /** 0 for legacy, 1 for virtio 1.0 */ - int virtio_version; - - /** Virtio 1.0 device data */ - struct virtio_pci_modern_device vdev; - /** RX/TX virtqueues */ struct vring_virtqueue *virtqueue; @@ -105,7 +98,7 @@ struct virtnet_nic { unsigned int rx_num_iobufs; /** Virtio net packet header, we only need one */ - struct virtio_net_hdr_modern empty_header; + struct virtio_net_hdr empty_header; }; /** Add an iobuf to a virtqueue @@ -122,9 +115,6 @@ static void virtnet_enqueue_iob ( struct net_device *netdev, struct vring_virtqueue *vq = &virtnet->virtqueue[vq_idx]; unsigned int out = ( vq_idx == TX_INDEX ) ? 2 : 0; unsigned int in = ( vq_idx == TX_INDEX ) ? 0 : 2; - size_t header_len = virtnet->virtio_version - ? sizeof ( virtnet->empty_header ) - : sizeof ( virtnet->empty_header.legacy ); struct vring_list list[] = { { /* Share a single zeroed virtio net header between all @@ -133,7 +123,7 @@ static void virtnet_enqueue_iob ( struct net_device *netdev, * header fields get used. */ .addr = ( char* ) &virtnet->empty_header, - .length = header_len, + .length = sizeof ( virtnet->empty_header ), }, { .addr = ( char* ) iobuf->data, @@ -145,8 +135,7 @@ static void virtnet_enqueue_iob ( struct net_device *netdev, virtnet, iobuf, vq_idx ); vring_add_buf ( vq, list, out, in, iobuf, 0 ); - vring_kick ( virtnet->virtio_version ? &virtnet->vdev : NULL, - virtnet->ioaddr, vq, 1 ); + vring_kick ( virtnet->ioaddr, vq, 1 ); } /** Try to keep rx virtqueue filled with iobufs @@ -175,12 +164,12 @@ static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) { } } -/** Open network device, legacy virtio 0.9.5 +/** Open network device * * @v netdev Network device * @ret rc Return status code */ -static int virtnet_open_legacy ( struct net_device *netdev ) { +static int virtnet_open ( struct net_device *netdev ) { struct virtnet_nic *virtnet = netdev->priv; unsigned long ioaddr = virtnet->ioaddr; u32 features; @@ -221,81 +210,6 @@ static int virtnet_open_legacy ( struct net_device *netdev ) { return 0; } -/** Open network device, modern virtio 1.0 - * - * @v netdev Network device - * @ret rc Return status code - */ -static int virtnet_open_modern ( struct net_device *netdev ) { - struct virtnet_nic *virtnet = netdev->priv; - u64 features; - u8 status; - - /* Negotiate features */ - features = vpm_get_features ( &virtnet->vdev ); - if ( ! ( features & VIRTIO_F_VERSION_1 ) ) { - vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED ); - return -EINVAL; - } - vpm_set_features ( &virtnet->vdev, features & ( - ( 1ULL << VIRTIO_NET_F_MAC ) | - ( 1ULL << VIRTIO_F_VERSION_1 ) | - ( 1ULL << VIRTIO_F_ANY_LAYOUT ) ) ); - vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FEATURES_OK ); - - status = vpm_get_status ( &virtnet->vdev ); - if ( ! ( status & VIRTIO_CONFIG_S_FEATURES_OK ) ) { - DBGC ( virtnet, "VIRTIO-NET %p device didn't accept features\n", - virtnet ); - vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED ); - return -EINVAL; - } - - /* Allocate virtqueues */ - virtnet->virtqueue = zalloc ( QUEUE_NB * - sizeof ( *virtnet->virtqueue ) ); - if ( ! virtnet->virtqueue ) { - vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED ); - return -ENOMEM; - } - - /* Initialize rx/tx virtqueues */ - if ( vpm_find_vqs ( &virtnet->vdev, QUEUE_NB, virtnet->virtqueue ) ) { - DBGC ( virtnet, "VIRTIO-NET %p cannot register queues\n", - virtnet ); - free ( virtnet->virtqueue ); - virtnet->virtqueue = NULL; - vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED ); - return -ENOENT; - } - - /* Disable interrupts before starting */ - netdev_irq ( netdev, 0 ); - - vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER_OK ); - - /* Initialize rx packets */ - INIT_LIST_HEAD ( &virtnet->rx_iobufs ); - virtnet->rx_num_iobufs = 0; - virtnet_refill_rx_virtqueue ( netdev ); - return 0; -} - -/** Open network device - * - * @v netdev Network device - * @ret rc Return status code - */ -static int virtnet_open ( struct net_device *netdev ) { - struct virtnet_nic *virtnet = netdev->priv; - - if ( virtnet->virtio_version ) { - return virtnet_open_modern ( netdev ); - } else { - return virtnet_open_legacy ( netdev ); - } -} - /** Close network device * * @v netdev Network device @@ -304,19 +218,10 @@ static void virtnet_close ( struct net_device *netdev ) { struct virtnet_nic *virtnet = netdev->priv; struct io_buffer *iobuf; struct io_buffer *next_iobuf; - int i; - if ( virtnet->virtio_version ) { - vpm_reset ( &virtnet->vdev ); - } else { - vp_reset ( virtnet->ioaddr ); - } + vp_reset ( virtnet->ioaddr ); /* Virtqueues can be freed now that NIC is reset */ - for ( i = 0 ; i < QUEUE_NB ; i++ ) { - virtio_pci_unmap_capability ( &virtnet->virtqueue[i].notification ); - } - free ( virtnet->virtqueue ); virtnet->virtqueue = NULL; @@ -397,14 +302,10 @@ static void virtnet_poll ( struct net_device *netdev ) { /* Acknowledge interrupt. This is necessary for UNDI operation and * interrupts that are raised despite VRING_AVAIL_F_NO_INTERRUPT being - * set (that flag is just a hint and the hypervisor does not have to + * set (that flag is just a hint and the hypervisor not not have to * honor it). */ - if ( virtnet->virtio_version ) { - vpm_get_isr ( &virtnet->vdev ); - } else { - vp_get_isr ( virtnet->ioaddr ); - } + vp_get_isr ( virtnet->ioaddr ); virtnet_process_tx_packets ( netdev ); virtnet_process_rx_packets ( netdev ); @@ -437,12 +338,13 @@ static struct net_device_operations virtnet_operations = { }; /** - * Probe PCI device, legacy virtio 0.9.5 + * Probe PCI device * * @v pci PCI device + * @v id PCI ID * @ret rc Return status code */ -static int virtnet_probe_legacy ( struct pci_device *pci ) { +static int virtnet_probe ( struct pci_device *pci ) { unsigned long ioaddr = pci->ioaddr; struct net_device *netdev; struct virtnet_nic *virtnet; @@ -493,154 +395,12 @@ static int virtnet_probe_legacy ( struct pci_device *pci ) { } /** - * Probe PCI device, modern virtio 1.0 - * - * @v pci PCI device - * @v found_dev Set to non-zero if modern device was found (probe may still fail) - * @ret rc Return status code - */ -static int virtnet_probe_modern ( struct pci_device *pci, int *found_dev ) { - struct net_device *netdev; - struct virtnet_nic *virtnet; - u64 features; - int rc, common, isr, notify, config, device; - - common = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_COMMON_CFG ); - if ( ! common ) { - DBG ( "Common virtio capability not found!\n" ); - return -ENODEV; - } - *found_dev = 1; - - isr = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_ISR_CFG ); - notify = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_NOTIFY_CFG ); - config = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_PCI_CFG ); - if ( ! isr || ! notify || ! config ) { - DBG ( "Missing virtio capabilities %i/%i/%i/%i\n", - common, isr, notify, config ); - return -EINVAL; - } - device = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_DEVICE_CFG ); - - /* Allocate and hook up net device */ - netdev = alloc_etherdev ( sizeof ( *virtnet ) ); - if ( ! netdev ) - return -ENOMEM; - netdev_init ( netdev, &virtnet_operations ); - virtnet = netdev->priv; - - pci_set_drvdata ( pci, netdev ); - netdev->dev = &pci->dev; - - DBGC ( virtnet, "VIRTIO-NET modern %p busaddr=%s irq=%d\n", - virtnet, pci->dev.name, pci->irq ); - - virtnet->vdev.pci = pci; - rc = virtio_pci_map_capability ( pci, common, - sizeof ( struct virtio_pci_common_cfg ), 4, - 0, sizeof ( struct virtio_pci_common_cfg ), - &virtnet->vdev.common ); - if ( rc ) - goto err_map_common; - - rc = virtio_pci_map_capability ( pci, isr, sizeof ( u8 ), 1, - 0, 1, - &virtnet->vdev.isr ); - if ( rc ) - goto err_map_isr; - - virtnet->vdev.notify_cap_pos = notify; - virtnet->vdev.cfg_cap_pos = config; - - /* Map the device capability */ - if ( device ) { - rc = virtio_pci_map_capability ( pci, device, - 0, 4, 0, sizeof ( struct virtio_net_config ), - &virtnet->vdev.device ); - if ( rc ) - goto err_map_device; - } - - /* Enable the PCI device */ - adjust_pci_device ( pci ); - - /* Reset the device and set initial status bits */ - vpm_reset ( &virtnet->vdev ); - vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE ); - vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER ); - - /* Load MAC address */ - if ( device ) { - features = vpm_get_features ( &virtnet->vdev ); - if ( features & ( 1ULL << VIRTIO_NET_F_MAC ) ) { - vpm_get ( &virtnet->vdev, - offsetof ( struct virtio_net_config, mac ), - netdev->hw_addr, ETH_ALEN ); - DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet, - eth_ntoa ( netdev->hw_addr ) ); - } - } - - /* We need a valid MAC address */ - if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) { - rc = -EADDRNOTAVAIL; - goto err_mac_address; - } - - /* Register network device */ - if ( ( rc = register_netdev ( netdev ) ) != 0 ) - goto err_register_netdev; - - /* Mark link as up, control virtqueue is not used */ - netdev_link_up ( netdev ); - - virtnet->virtio_version = 1; - return 0; - - unregister_netdev ( netdev ); -err_register_netdev: -err_mac_address: - vpm_reset ( &virtnet->vdev ); - netdev_nullify ( netdev ); - netdev_put ( netdev ); - - virtio_pci_unmap_capability ( &virtnet->vdev.device ); -err_map_device: - virtio_pci_unmap_capability ( &virtnet->vdev.isr ); -err_map_isr: - virtio_pci_unmap_capability ( &virtnet->vdev.common ); -err_map_common: - return rc; -} - -/** - * Probe PCI device - * - * @v pci PCI device - * @ret rc Return status code - */ -static int virtnet_probe ( struct pci_device *pci ) { - int found_modern = 0; - int rc = virtnet_probe_modern ( pci, &found_modern ); - if ( ! found_modern && pci->device < 0x1040 ) { - /* fall back to the legacy probe */ - rc = virtnet_probe_legacy ( pci ); - } - return rc; -} - -/** * Remove device * * @v pci PCI device */ static void virtnet_remove ( struct pci_device *pci ) { struct net_device *netdev = pci_get_drvdata ( pci ); - struct virtnet_nic *virtnet = netdev->priv; - - virtio_pci_unmap_capability ( &virtnet->vdev.device ); - virtio_pci_unmap_capability ( &virtnet->vdev.isr ); - virtio_pci_unmap_capability ( &virtnet->vdev.common ); unregister_netdev ( netdev ); netdev_nullify ( netdev ); @@ -649,7 +409,6 @@ static void virtnet_remove ( struct pci_device *pci ) { static struct pci_device_id virtnet_nics[] = { PCI_ROM(0x1af4, 0x1000, "virtio-net", "Virtio Network Interface", 0), -PCI_ROM(0x1af4, 0x1041, "virtio-net", "Virtio Network Interface 1.0", 0), }; struct pci_driver virtnet_driver __pci_driver = { diff --git a/roms/ipxe/src/drivers/net/virtio-net.h b/roms/ipxe/src/drivers/net/virtio-net.h index c2b4a17cc..3abef28ea 100644 --- a/roms/ipxe/src/drivers/net/virtio-net.h +++ b/roms/ipxe/src/drivers/net/virtio-net.h @@ -14,12 +14,6 @@ #define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ #define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ #define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ -#define VIRTIO_NET_F_MRG_RXBUF 15 /* Driver can merge receive buffers. */ -#define VIRTIO_NET_F_STATUS 16 /* Configuration status field is available. */ -#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel is available. */ -#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support. */ -#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering. */ -#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Driver can send gratuitous packets. */ struct virtio_net_config { @@ -47,14 +41,4 @@ struct virtio_net_hdr uint16_t csum_start; uint16_t csum_offset; }; - -/* Virtio 1.0 version of the first element of the scatter-gather list. */ -struct virtio_net_hdr_modern -{ - struct virtio_net_hdr legacy; - - /* Used only if VIRTIO_NET_F_MRG_RXBUF: */ - uint16_t num_buffers; -}; - #endif /* _VIRTIO_NET_H_ */ diff --git a/roms/ipxe/src/drivers/net/vmxnet3.c b/roms/ipxe/src/drivers/net/vmxnet3.c index 6a54dbf89..8d4f4b843 100644 --- a/roms/ipxe/src/drivers/net/vmxnet3.c +++ b/roms/ipxe/src/drivers/net/vmxnet3.c @@ -92,24 +92,19 @@ static int vmxnet3_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { struct vmxnet3_nic *vmxnet = netdev_priv ( netdev ); struct vmxnet3_tx_desc *tx_desc; - unsigned int fill; unsigned int desc_idx; unsigned int generation; /* Check that we have a free transmit descriptor */ - fill = ( vmxnet->count.tx_prod - vmxnet->count.tx_cons ); - if ( fill >= VMXNET3_TX_FILL ) { + desc_idx = ( vmxnet->count.tx_prod % VMXNET3_NUM_TX_DESC ); + generation = ( ( vmxnet->count.tx_prod & VMXNET3_NUM_TX_DESC ) ? + 0 : cpu_to_le32 ( VMXNET3_TXF_GEN ) ); + if ( vmxnet->tx_iobuf[desc_idx] ) { DBGC ( vmxnet, "VMXNET3 %p out of transmit descriptors\n", vmxnet ); return -ENOBUFS; } - /* Locate transmit descriptor */ - desc_idx = ( vmxnet->count.tx_prod % VMXNET3_NUM_TX_DESC ); - generation = ( ( vmxnet->count.tx_prod & VMXNET3_NUM_TX_DESC ) ? - 0 : cpu_to_le32 ( VMXNET3_TXF_GEN ) ); - assert ( vmxnet->tx_iobuf[desc_idx] == NULL ); - /* Increment producer counter */ vmxnet->count.tx_prod++; diff --git a/roms/ipxe/src/drivers/net/vmxnet3.h b/roms/ipxe/src/drivers/net/vmxnet3.h index 5e1e0cb6e..a1671d9dd 100644 --- a/roms/ipxe/src/drivers/net/vmxnet3.h +++ b/roms/ipxe/src/drivers/net/vmxnet3.h @@ -493,9 +493,6 @@ struct vmxnet3_nic { /** MTU size */ #define VMXNET3_MTU ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* FCS */ ) -/** Transmit ring maximum fill level */ -#define VMXNET3_TX_FILL ( VMXNET3_NUM_TX_DESC - 1 ) - /** Receive ring maximum fill level */ #define VMXNET3_RX_FILL 8 diff --git a/roms/ipxe/src/drivers/usb/ehci.c b/roms/ipxe/src/drivers/usb/ehci.c index 35cbc8de9..4124692a6 100644 --- a/roms/ipxe/src/drivers/usb/ehci.c +++ b/roms/ipxe/src/drivers/usb/ehci.c @@ -175,61 +175,6 @@ static int ehci_ctrl_reachable ( struct ehci_device *ehci, void *ptr ) { /****************************************************************************** * - * Diagnostics - * - ****************************************************************************** - */ - -/** - * Dump host controller registers - * - * @v ehci EHCI device - */ -static __unused void ehci_dump ( struct ehci_device *ehci ) { - uint8_t caplength; - uint16_t hciversion; - uint32_t hcsparams; - uint32_t hccparams; - uint32_t usbcmd; - uint32_t usbsts; - uint32_t usbintr; - uint32_t frindex; - uint32_t ctrldssegment; - uint32_t periodiclistbase; - uint32_t asynclistaddr; - uint32_t configflag; - - /* Do nothing unless debugging is enabled */ - if ( ! DBG_LOG ) - return; - - /* Dump capability registers */ - caplength = readb ( ehci->cap + EHCI_CAP_CAPLENGTH ); - hciversion = readw ( ehci->cap + EHCI_CAP_HCIVERSION ); - hcsparams = readl ( ehci->cap + EHCI_CAP_HCSPARAMS ); - hccparams = readl ( ehci->cap + EHCI_CAP_HCCPARAMS ); - DBGC ( ehci, "EHCI %s caplen %02x hciversion %04x hcsparams %08x " - "hccparams %08x\n", ehci->name, caplength, hciversion, - hcsparams, hccparams ); - - /* Dump operational registers */ - usbcmd = readl ( ehci->op + EHCI_OP_USBCMD ); - usbsts = readl ( ehci->op + EHCI_OP_USBSTS ); - usbintr = readl ( ehci->op + EHCI_OP_USBINTR ); - frindex = readl ( ehci->op + EHCI_OP_FRINDEX ); - ctrldssegment = readl ( ehci->op + EHCI_OP_CTRLDSSEGMENT ); - periodiclistbase = readl ( ehci->op + EHCI_OP_PERIODICLISTBASE ); - asynclistaddr = readl ( ehci->op + EHCI_OP_ASYNCLISTADDR ); - configflag = readl ( ehci->op + EHCI_OP_CONFIGFLAG ); - DBGC ( ehci, "EHCI %s usbcmd %08x usbsts %08x usbint %08x frindx " - "%08x\n", ehci->name, usbcmd, usbsts, usbintr, frindex ); - DBGC ( ehci, "EHCI %s ctrlds %08x period %08x asyncl %08x cfgflg " - "%08x\n", ehci->name, ctrldssegment, periodiclistbase, - asynclistaddr, configflag ); -} - -/****************************************************************************** - * * USB legacy support * ****************************************************************************** @@ -288,14 +233,6 @@ static void ehci_legacy_claim ( struct ehci_device *ehci, if ( ! legacy ) return; - /* Dump original SMI usage */ - pci_read_config_dword ( pci, ( legacy + EHCI_USBLEGSUP_CTLSTS ), - &ctlsts ); - if ( ctlsts ) { - DBGC ( ehci, "EHCI %s BIOS using SMIs: %08x\n", - ehci->name, ctlsts ); - } - /* Claim ownership */ pci_write_config_byte ( pci, ( legacy + EHCI_USBLEGSUP_OS ), EHCI_USBLEGSUP_OS_OWNED ); @@ -339,11 +276,9 @@ static void ehci_legacy_claim ( struct ehci_device *ehci, */ static void ehci_legacy_release ( struct ehci_device *ehci, struct pci_device *pci ) { - unsigned int legacy = ehci->legacy; - uint32_t ctlsts; /* Do nothing unless legacy support capability is present */ - if ( ! legacy ) + if ( ! ehci->legacy ) return; /* Do nothing if releasing ownership is prevented */ @@ -354,14 +289,8 @@ static void ehci_legacy_release ( struct ehci_device *ehci, } /* Release ownership */ - pci_write_config_byte ( pci, ( legacy + EHCI_USBLEGSUP_OS ), 0 ); + pci_write_config_byte ( pci, ( ehci->legacy + EHCI_USBLEGSUP_OS ), 0 ); DBGC ( ehci, "EHCI %s released ownership to BIOS\n", ehci->name ); - - /* Dump restored SMI usage */ - pci_read_config_dword ( pci, ( legacy + EHCI_USBLEGSUP_CTLSTS ), - &ctlsts ); - DBGC ( ehci, "EHCI %s BIOS reclaimed SMIs: %08x\n", - ehci->name, ctlsts ); } /****************************************************************************** @@ -674,8 +603,6 @@ static int ehci_enqueue ( struct ehci_device *ehci, struct ehci_ring *ring, /* Fail if any portion is unreachable */ for ( i = 0 ; i < count ; i++ ) { - if ( ! xfer[i].len ) - continue; phys = ( virt_to_phys ( xfer[i].data ) + xfer[i].len - 1 ); if ( ( phys > 0xffffffffUL ) && ( ! ehci->addr64 ) ) return -ENOTSUP; @@ -1041,10 +968,10 @@ static uint32_t ehci_endpoint_characteristics ( struct usb_endpoint *ep ) { chr |= EHCI_CHR_TOGGLE; /* Determine endpoint speed */ - if ( usb->speed == USB_SPEED_HIGH ) { + if ( usb->port->speed == USB_SPEED_HIGH ) { chr |= EHCI_CHR_EPS_HIGH; } else { - if ( usb->speed == USB_SPEED_FULL ) { + if ( usb->port->speed == USB_SPEED_FULL ) { chr |= EHCI_CHR_EPS_FULL; } else { chr |= EHCI_CHR_EPS_LOW; @@ -1292,75 +1219,40 @@ static int ehci_endpoint_message ( struct usb_endpoint *ep, } /** - * Calculate number of transfer descriptors - * - * @v len Length of data - * @v zlp Append a zero-length packet - * @ret count Number of transfer descriptors - */ -static unsigned int ehci_endpoint_count ( size_t len, int zlp ) { - unsigned int count; - - /* Split into 16kB transfers. A single transfer can handle up - * to 20kB if it happens to be page-aligned, or up to 16kB - * with arbitrary alignment. We simplify the code by assuming - * that we can fit only 16kB into each transfer. - */ - count = ( ( len + EHCI_MTU - 1 ) / EHCI_MTU ); - - /* Append a zero-length transfer if applicable */ - if ( zlp || ( count == 0 ) ) - count++; - - return count; -} - -/** * Enqueue stream transfer * * @v ep USB endpoint * @v iobuf I/O buffer - * @v zlp Append a zero-length packet + * @v terminate Terminate using a short packet * @ret rc Return status code */ static int ehci_endpoint_stream ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int zlp ) { + struct io_buffer *iobuf, int terminate ) { struct ehci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep ); struct ehci_device *ehci = endpoint->ehci; - void *data = iobuf->data; - size_t len = iob_len ( iobuf ); - unsigned int count = ehci_endpoint_count ( len, zlp ); unsigned int input = ( ep->address & USB_DIR_IN ); - unsigned int flags = ( input ? EHCI_FL_PID_IN : EHCI_FL_PID_OUT ); - struct ehci_transfer xfers[count]; + struct ehci_transfer xfers[2]; struct ehci_transfer *xfer = xfers; - size_t xfer_len; - unsigned int i; + size_t len = iob_len ( iobuf ); int rc; - /* Create transfers */ - for ( i = 0 ; i < count ; i++ ) { - - /* Calculate transfer length */ - xfer_len = EHCI_MTU; - if ( xfer_len > len ) - xfer_len = len; - - /* Create transfer */ - xfer->data = data; - xfer->len = xfer_len; - xfer->flags = flags; - - /* Move to next transfer */ - data += xfer_len; - len -= xfer_len; + /* Create transfer */ + xfer->data = iobuf->data; + xfer->len = len; + xfer->flags = ( EHCI_FL_IOC | + ( input ? EHCI_FL_PID_IN : EHCI_FL_PID_OUT ) ); + xfer++; + if ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) ) { + xfer->data = NULL; + xfer->len = 0; + assert ( ! input ); + xfer->flags = ( EHCI_FL_IOC | EHCI_FL_PID_OUT ); xfer++; } - xfer[-1].flags |= EHCI_FL_IOC; /* Enqueue transfer */ if ( ( rc = ehci_enqueue ( ehci, &endpoint->ring, iobuf, xfers, - count ) ) != 0 ) + ( xfer - xfers ) ) ) != 0 ) return rc; return 0; diff --git a/roms/ipxe/src/drivers/usb/uhci.c b/roms/ipxe/src/drivers/usb/uhci.c index 528c1be1d..b6bb92560 100644 --- a/roms/ipxe/src/drivers/usb/uhci.c +++ b/roms/ipxe/src/drivers/usb/uhci.c @@ -697,7 +697,7 @@ static int uhci_endpoint_open ( struct usb_endpoint *ep ) { goto err_ring_alloc; endpoint->ring.mtu = ep->mtu; endpoint->ring.flags = UHCI_FL_CERR_MAX; - if ( usb->speed < USB_SPEED_FULL ) + if ( usb->port->speed < USB_SPEED_FULL ) endpoint->ring.flags |= UHCI_FL_LS; endpoint->ring.control = ( UHCI_CONTROL_DEVICE ( usb->address ) | UHCI_CONTROL_ENDPOINT ( ep->address ) ); @@ -835,20 +835,22 @@ static int uhci_endpoint_message ( struct usb_endpoint *ep, * * @v ep USB endpoint * @v iobuf I/O buffer - * @v zlp Append a zero-length packet + * @v terminate Terminate using a short packet * @ret rc Return status code */ static int uhci_endpoint_stream ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int zlp ) { + struct io_buffer *iobuf, int terminate ) { struct uhci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep ); struct uhci_ring *ring = &endpoint->ring; unsigned int count; size_t len; int input; + int zlp; int rc; /* Calculate number of descriptors */ len = iob_len ( iobuf ); + zlp = ( terminate && ( ( len & ( ring->mtu - 1 ) ) == 0 ) ); count = ( ( ( len + ring->mtu - 1 ) / ring->mtu ) + ( zlp ? 1 : 0 ) ); /* Enqueue transfer */ diff --git a/roms/ipxe/src/drivers/usb/usbhub.c b/roms/ipxe/src/drivers/usb/usbhub.c index 47914bcdb..bf2a20005 100644 --- a/roms/ipxe/src/drivers/usb/usbhub.c +++ b/roms/ipxe/src/drivers/usb/usbhub.c @@ -155,10 +155,6 @@ static int hub_open ( struct usb_hub *hub ) { /* Refill interrupt ring */ hub_refill ( hubdev ); - /* Delay to allow ports to stabilise on out-of-spec hubs */ - if ( hubdev->flags & USB_HUB_SLOW_START ) - mdelay ( USB_HUB_SLOW_START_DELAY_MS ); - return 0; usb_endpoint_close ( &hubdev->intr ); @@ -414,9 +410,8 @@ static int hub_probe ( struct usb_function *func, hubdev->usb = usb; hubdev->features = ( enhanced ? USB_HUB_FEATURES_ENHANCED : USB_HUB_FEATURES ); - hubdev->flags = func->id->driver_data; usb_endpoint_init ( &hubdev->intr, usb, &usb_hub_intr_operations ); - usb_refill_init ( &hubdev->intr, 0, 0, USB_HUB_INTR_FILL ); + usb_refill_init ( &hubdev->intr, 0, USB_HUB_INTR_FILL ); process_init_stopped ( &hubdev->refill, &hub_refill_desc, NULL ); /* Locate hub interface descriptor */ @@ -501,10 +496,9 @@ static void hub_remove ( struct usb_function *func ) { unsigned int i; /* If hub has been unplugged, mark all ports as unplugged */ - if ( usb->port->disconnected ) { + if ( usb->port->speed == USB_SPEED_NONE ) { for ( i = 1 ; i <= hub->ports ; i++ ) { port = usb_port ( hub, i ); - port->disconnected = 1; port->speed = USB_SPEED_NONE; } } @@ -523,15 +517,24 @@ static void hub_remove ( struct usb_function *func ) { /** USB hub device IDs */ static struct usb_device_id hub_ids[] = { { - .name = "avocent-hub", - .vendor = 0x0624, - .product = 0x0248, - .driver_data = USB_HUB_SLOW_START, + .name = "hub-1", + .vendor = USB_ANY_ID, + .product = USB_ANY_ID, + .class = { + .class = USB_CLASS_HUB, + .subclass = 0, + .protocol = 0, + }, }, { - .name = "hub", + .name = "hub-2", .vendor = USB_ANY_ID, .product = USB_ANY_ID, + .class = { + .class = USB_CLASS_HUB, + .subclass = 0, + .protocol = 1, + }, }, }; @@ -539,8 +542,6 @@ static struct usb_device_id hub_ids[] = { struct usb_driver usb_hub_driver __usb_driver = { .ids = hub_ids, .id_count = ( sizeof ( hub_ids ) / sizeof ( hub_ids[0] ) ), - .class = USB_CLASS_ID ( USB_CLASS_HUB, 0, USB_ANY_ID ), - .score = USB_SCORE_NORMAL, .probe = hub_probe, .remove = hub_remove, }; diff --git a/roms/ipxe/src/drivers/usb/usbhub.h b/roms/ipxe/src/drivers/usb/usbhub.h index a5f123acc..d7d8f9610 100644 --- a/roms/ipxe/src/drivers/usb/usbhub.h +++ b/roms/ipxe/src/drivers/usb/usbhub.h @@ -257,8 +257,6 @@ struct usb_hub_device { struct usb_hub *hub; /** Features */ unsigned int features; - /** Flags */ - unsigned int flags; /** Interrupt endpoint */ struct usb_endpoint intr; @@ -266,12 +264,6 @@ struct usb_hub_device { struct process refill; }; -/** Hub requires additional settling delay */ -#define USB_HUB_SLOW_START 0x0001 - -/** Additional setting delay for out-of-spec hubs */ -#define USB_HUB_SLOW_START_DELAY_MS 500 - /** Interrupt ring fill level * * This is a policy decision. diff --git a/roms/ipxe/src/drivers/usb/usbio.c b/roms/ipxe/src/drivers/usb/usbio.c deleted file mode 100644 index 153f39421..000000000 --- a/roms/ipxe/src/drivers/usb/usbio.c +++ /dev/null @@ -1,1717 +0,0 @@ -/* - * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * You can also choose to distribute this program under the terms of - * the Unmodified Binary Distribution Licence (as given in the file - * COPYING.UBDL), provided that you have satisfied its requirements. - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/efi_driver.h> -#include <ipxe/efi/efi_utils.h> -#include <ipxe/efi/Protocol/UsbIo.h> -#include <ipxe/usb.h> -#include "usbio.h" - -/** @file - * - * EFI_USB_IO_PROTOCOL pseudo Host Controller Interface driver - * - * - * The EFI_USB_IO_PROTOCOL is an almost unbelievably poorly designed - * abstraction of a USB device. It would be just about forgivable for - * an API to support only synchronous operation for bulk OUT - * endpoints. It is imbecilic to support only synchronous operation - * for bulk IN endpoints. This apparently intern-designed API - * throttles a typical NIC down to 1.5% of its maximum throughput. - * That isn't a typo. It really is that slow. - * - * We can't even work around this stupidity by talking to the host - * controller abstraction directly, because an identical limitation - * exists in the EFI_USB2_HC_PROTOCOL. - * - * Unless you derive therapeutic value from watching download progress - * indicators lethargically creep through every single integer from 0 - * to 100, you should use iPXE's native USB host controller drivers - * instead. (Or just upgrade from UEFI to "legacy" BIOS, which will - * produce a similar speed increase.) - * - * - * For added excitement, the EFI_USB_IO_PROTOCOL makes the - * (demonstrably incorrect) assumption that a USB driver needs to - * attach to exactly one interface within a USB device, and provides a - * helper method to retrieve "the" interface descriptor. Since pretty - * much every USB network device requires binding to a pair of - * control+data interfaces, this aspect of EFI_USB_IO_PROTOCOL is of - * no use to us. - * - * We have our own existing code for reading USB descriptors, so we - * don't actually care that the UsbGetInterfaceDescriptor() method - * provided by EFI_USB_IO_PROTOCOL is useless for network devices. We - * can read the descriptors ourselves (via UsbControlTransfer()) and - * get all of the information we need this way. We can even work - * around the fact that EFI_USB_IO_PROTOCOL provides separate handles - * for each of the two interfaces comprising our network device. - * - * However, if we discover that we need to select an alternative - * device configuration (e.g. for devices exposing both RNDIS and - * ECM), then all hell breaks loose. EFI_USB_IO_PROTOCOL starts to - * panic because its cached interface and endpoint descriptors will no - * longer be valid. As mentioned above, the cached descriptors are - * useless for network devices anyway so we _really_ don't care about - * this, but EFI_USB_IO_PROTOCOL certainly cares. It prints out a - * manic warning message containing no fewer than six exclamation - * marks and then literally commits seppuku in the middle of the - * UsbControlTransfer() method by attempting to uninstall itself. - * Quite how the caller is supposed to react when asked to stop using - * the EFI_USB_IO_PROTOCOL instance while in the middle of an - * uninterruptible call to said instance is left as an exercise for - * the interested reader. - * - * There is no sensible way to work around this, so we just - * preemptively fail if asked to change the device configuration, on - * the basis that reporting a sarcastic error message is often - * preferable to jumping through a NULL pointer and crashing the - * system. - */ - -/* Disambiguate the various error causes */ -#define ENOTSUP_MORONIC_SPECIFICATION \ - __einfo_error ( EINFO_ENOTSUP_MORONIC_SPECIFICATION ) -#define EINFO_ENOTSUP_MORONIC_SPECIFICATION \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \ - "EFI_USB_IO_PROTOCOL was designed by morons" ) - -/****************************************************************************** - * - * Device model - * - ****************************************************************************** - */ - -/** - * Determine endpoint interface number - * - * @v usbio USB I/O device - * @v ep USB Endpoint - * @ret interface Interface number, or negative error - */ -static int usbio_interface ( struct usbio_device *usbio, - struct usb_endpoint *ep ) { - EFI_HANDLE handle = usbio->handle; - struct usb_device *usb = ep->usb; - struct usb_configuration_descriptor *config; - struct usb_interface_descriptor *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_function *func; - unsigned int i; - - /* The control endpoint is not part of a described interface */ - if ( ep->address == USB_EP0_ADDRESS ) - return 0; - - /* Iterate over all interface descriptors looking for a match */ - config = usbio->config; - for_each_config_descriptor ( interface, config ) { - - /* Skip non-interface descriptors */ - if ( interface->header.type != USB_INTERFACE_DESCRIPTOR ) - continue; - - /* Iterate over all endpoint descriptors looking for a match */ - for_each_interface_descriptor ( endpoint, config, interface ) { - - /* Skip non-endpoint descriptors */ - if ( endpoint->header.type != USB_ENDPOINT_DESCRIPTOR ) - continue; - - /* Check endpoint address */ - if ( endpoint->endpoint != ep->address ) - continue; - - /* Check interface belongs to this function */ - list_for_each_entry ( func, &usb->functions, list ) { - - /* Skip non-matching functions */ - if ( func->interface[0] != usbio->first ) - continue; - - /* Iterate over all interfaces for a match */ - for ( i = 0 ; i < func->desc.count ; i++ ) { - if ( interface->interface == - func->interface[i] ) - return interface->interface; - } - } - } - } - - DBGC ( usbio, "USBIO %s cannot find interface for %s", - efi_handle_name ( handle ), usb_endpoint_name ( ep ) ); - return -ENOENT; -} - -/** - * Open USB I/O interface - * - * @v usbio USB I/O device - * @v interface Interface number - * @ret rc Return status code - */ -static int usbio_open ( struct usbio_device *usbio, unsigned int interface ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE handle = usbio->handle; - struct usbio_interface *intf = &usbio->interface[interface]; - EFI_DEVICE_PATH_PROTOCOL *path; - EFI_DEVICE_PATH_PROTOCOL *end; - USB_DEVICE_PATH *usbpath; - union { - void *interface; - EFI_USB_IO_PROTOCOL *io; - } u; - EFI_STATUS efirc; - int rc; - - /* Sanity check */ - assert ( interface < usbio->config->interfaces ); - - /* If interface is already open, just increment the usage count */ - if ( intf->count ) { - intf->count++; - return 0; - } - - /* Construct device path for this interface */ - path = usbio->path; - usbpath = usbio->usbpath; - usbpath->InterfaceNumber = interface; - end = efi_devpath_end ( path ); - - /* Locate handle for this endpoint's interface */ - if ( ( efirc = bs->LocateDevicePath ( &efi_usb_io_protocol_guid, &path, - &intf->handle ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( usbio, "USBIO %s could not locate ", - efi_handle_name ( handle ) ); - DBGC ( usbio, "%s: %s\n", - efi_devpath_text ( usbio->path ), strerror ( rc ) ); - return rc; - } - - /* Check that expected path was located */ - if ( path != end ) { - DBGC ( usbio, "USBIO %s located incomplete ", - efi_handle_name ( handle ) ); - DBGC ( usbio, "%s\n", efi_handle_name ( intf->handle ) ); - return -EXDEV; - } - - /* Open USB I/O protocol on this handle */ - if ( ( efirc = bs->OpenProtocol ( intf->handle, - &efi_usb_io_protocol_guid, - &u.interface, efi_image_handle, - intf->handle, - ( EFI_OPEN_PROTOCOL_BY_DRIVER | - EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){ - rc = -EEFI ( efirc ); - DBGC ( usbio, "USBIO %s cannot open ", - efi_handle_name ( handle ) ); - DBGC ( usbio, "%s: %s\n", - efi_handle_name ( intf->handle ), strerror ( rc ) ); - DBGC_EFI_OPENERS ( usbio, intf->handle, - &efi_usb_io_protocol_guid ); - return rc; - } - intf->io = u.io; - - /* Increment usage count */ - intf->count++; - - return 0; -} - -/** - * Close USB I/O interface - * - * @v usbio USB I/O device - * @v interface Interface number - */ -static void usbio_close ( struct usbio_device *usbio, unsigned int interface ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - struct usbio_interface *intf = &usbio->interface[interface]; - - /* Sanity checks */ - assert ( interface < usbio->config->interfaces ); - assert ( intf->count > 0 ); - - /* Decrement usage count */ - intf->count--; - - /* Do nothing if interface is still in use */ - if ( intf->count ) - return; - - /* Close USB I/O protocol */ - bs->CloseProtocol ( intf->handle, &efi_usb_io_protocol_guid, - efi_image_handle, intf->handle ); -} - -/****************************************************************************** - * - * Control endpoints - * - ****************************************************************************** - */ - -/** - * Open control endpoint - * - * @v endpoint Endpoint - * @ret rc Return status code - */ -static int usbio_control_open ( struct usbio_endpoint *endpoint __unused ) { - - /* Nothing to do */ - return 0; -} - -/** - * Close control endpoint - * - * @v endpoint Endpoint - */ -static void usbio_control_close ( struct usbio_endpoint *endpoint __unused ) { - - /* Nothing to do */ -} - -/** - * Poll control endpoint - * - * @v endpoint Endpoint - */ -static void usbio_control_poll ( struct usbio_endpoint *endpoint ) { - struct usbio_device *usbio = endpoint->usbio; - struct usb_endpoint *ep = endpoint->ep; - EFI_HANDLE handle = usbio->handle; - EFI_USB_IO_PROTOCOL *io; - union { - struct usb_setup_packet setup; - EFI_USB_DEVICE_REQUEST efi; - } *msg; - EFI_USB_DATA_DIRECTION direction; - struct io_buffer *iobuf; - unsigned int index; - unsigned int flags; - unsigned int recipient; - unsigned int interface; - uint16_t request; - void *data; - size_t len; - UINT32 status; - EFI_STATUS efirc; - int rc; - - /* Do nothing if ring is empty */ - if ( endpoint->cons == endpoint->prod ) - return; - - /* Consume next transfer */ - index = ( endpoint->cons++ % USBIO_RING_COUNT ); - iobuf = endpoint->iobuf[index]; - flags = endpoint->flags[index]; - - /* Sanity check */ - if ( ! ( flags & USBIO_MESSAGE ) ) { - DBGC ( usbio, "USBIO %s %s non-message transfer\n", - efi_handle_name ( handle ), usb_endpoint_name ( ep ) ); - rc = -ENOTSUP; - goto err_not_message; - } - - /* Construct transfer */ - assert ( iob_len ( iobuf ) >= sizeof ( *msg ) ); - msg = iobuf->data; - iob_pull ( iobuf, sizeof ( *msg ) ); - request = le16_to_cpu ( msg->setup.request ); - len = iob_len ( iobuf ); - if ( len ) { - data = iobuf->data; - direction = ( ( request & USB_DIR_IN ) ? - EfiUsbDataIn : EfiUsbDataOut ); - } else { - data = NULL; - direction = EfiUsbNoData; - } - - /* Determine interface for this transfer */ - recipient = ( request & USB_RECIP_MASK ); - if ( recipient == USB_RECIP_INTERFACE ) { - /* Recipient is an interface: use interface number directly */ - interface = le16_to_cpu ( msg->setup.index ); - } else { - /* Route all other requests through the first interface */ - interface = 0; - } - - /* Open interface */ - if ( ( rc = usbio_open ( usbio, interface ) ) != 0 ) - goto err_open; - io = usbio->interface[interface].io; - - /* Due to the design of EFI_USB_IO_PROTOCOL, attempting to set - * the configuration to a non-default value is basically a - * self-destruct button. - */ - if ( ( request == USB_SET_CONFIGURATION ) && - ( le16_to_cpu ( msg->setup.value ) != usbio->config->config ) ) { - rc = -ENOTSUP_MORONIC_SPECIFICATION; - DBGC ( usbio, "USBIO %s cannot change configuration: %s\n", - efi_handle_name ( handle ), strerror ( rc ) ); - goto err_moronic_specification; - } - - /* Submit transfer */ - if ( ( efirc = io->UsbControlTransfer ( io, &msg->efi, direction, 0, - data, len, &status ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( usbio, "USBIO %s %s could not submit control transfer ", - efi_handle_name ( handle ), usb_endpoint_name ( ep ) ); - DBGC ( usbio, "via %s: %s (status %04x)\n", - efi_handle_name ( usbio->interface[interface].handle ), - strerror ( rc ), status ); - goto err_transfer; - } - - /* Close interface */ - usbio_close ( usbio, interface ); - - /* Complete transfer */ - usb_complete ( ep, iobuf ); - - return; - - err_transfer: - err_moronic_specification: - usbio_close ( usbio, interface ); - err_open: - err_not_message: - usb_complete_err ( ep, iobuf, rc ); -} - -/** Control endpoint operations */ -static struct usbio_operations usbio_control_operations = { - .open = usbio_control_open, - .close = usbio_control_close, - .poll = usbio_control_poll, -}; - -/****************************************************************************** - * - * Bulk IN endpoints - * - ****************************************************************************** - */ - -/** - * Open bulk IN endpoint - * - * @v endpoint Endpoint - * @ret rc Return status code - */ -static int usbio_bulk_in_open ( struct usbio_endpoint *endpoint __unused ) { - - /* Nothing to do */ - return 0; -} - -/** - * Close bulk IN endpoint - * - * @v endpoint Endpoint - */ -static void usbio_bulk_in_close ( struct usbio_endpoint *endpoint __unused ) { - - /* Nothing to do */ -} - -/** - * Poll bulk IN endpoint - * - * @v endpoint Endpoint - */ -static void usbio_bulk_in_poll ( struct usbio_endpoint *endpoint ) { - struct usbio_device *usbio = endpoint->usbio; - struct usb_endpoint *ep = endpoint->ep; - EFI_USB_IO_PROTOCOL *io = endpoint->io; - EFI_HANDLE handle = usbio->handle; - struct io_buffer *iobuf; - unsigned int index; - UINTN len; - UINT32 status; - EFI_STATUS efirc; - int rc; - - /* Do nothing if ring is empty */ - if ( endpoint->cons == endpoint->prod ) - return; - - /* Attempt (but do not yet consume) next transfer */ - index = ( endpoint->cons % USBIO_RING_COUNT ); - iobuf = endpoint->iobuf[index]; - - /* Construct transfer */ - len = iob_len ( iobuf ); - - /* Upon being turned on, the EFI_USB_IO_PROTOCOL did nothing - * for several minutes before firing a small ARP packet a few - * millimetres into the ether. - */ - efirc = io->UsbBulkTransfer ( io, ep->address, iobuf->data, - &len, 1, &status ); - if ( efirc == EFI_TIMEOUT ) - return; - - /* Consume transfer */ - endpoint->cons++; - - /* Check for failure */ - if ( efirc != 0 ) { - rc = -EEFI ( efirc ); - DBGC2 ( usbio, "USBIO %s %s could not submit bulk IN transfer: " - "%s (status %04x)\n", efi_handle_name ( handle ), - usb_endpoint_name ( ep ), strerror ( rc ), status ); - usb_complete_err ( ep, iobuf, rc ); - return; - } - - /* Update length */ - iob_put ( iobuf, ( len - iob_len ( iobuf ) ) ); - - /* Complete transfer */ - usb_complete ( ep, iobuf ); -} - -/** Bulk endpoint operations */ -static struct usbio_operations usbio_bulk_in_operations = { - .open = usbio_bulk_in_open, - .close = usbio_bulk_in_close, - .poll = usbio_bulk_in_poll, -}; - -/****************************************************************************** - * - * Bulk OUT endpoints - * - ****************************************************************************** - */ - -/** - * Open bulk OUT endpoint - * - * @v endpoint Endpoint - * @ret rc Return status code - */ -static int usbio_bulk_out_open ( struct usbio_endpoint *endpoint __unused ) { - - /* Nothing to do */ - return 0; -} - -/** - * Close bulk OUT endpoint - * - * @v endpoint Endpoint - */ -static void usbio_bulk_out_close ( struct usbio_endpoint *endpoint __unused ) { - - /* Nothing to do */ -} - -/** - * Poll bulk OUT endpoint - * - * @v endpoint Endpoint - */ -static void usbio_bulk_out_poll ( struct usbio_endpoint *endpoint ) { - struct usbio_device *usbio = endpoint->usbio; - struct usb_endpoint *ep = endpoint->ep; - EFI_USB_IO_PROTOCOL *io = endpoint->io; - EFI_HANDLE handle = usbio->handle; - struct io_buffer *iobuf; - unsigned int index; - unsigned int flags; - UINTN len; - UINT32 status; - EFI_STATUS efirc; - int rc; - - /* Do nothing if ring is empty */ - if ( endpoint->cons == endpoint->prod ) - return; - - /* Consume next transfer */ - index = ( endpoint->cons++ % USBIO_RING_COUNT ); - iobuf = endpoint->iobuf[index]; - flags = endpoint->flags[index]; - - /* Construct transfer */ - len = iob_len ( iobuf ); - - /* Submit transfer */ - if ( ( efirc = io->UsbBulkTransfer ( io, ep->address, iobuf->data, - &len, 0, &status ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( usbio, "USBIO %s %s could not submit bulk OUT transfer: " - "%s (status %04x)\n", efi_handle_name ( handle ), - usb_endpoint_name ( ep ), strerror ( rc ), status ); - goto err; - } - - /* Update length */ - iob_put ( iobuf, ( len - iob_len ( iobuf ) ) ); - - /* Submit zero-length transfer if required */ - len = 0; - if ( ( flags & USBIO_ZLEN ) && - ( efirc = io->UsbBulkTransfer ( io, ep->address, NULL, &len, 0, - &status ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( usbio, "USBIO %s %s could not submit zero-length " - "transfer: %s (status %04x)\n", - efi_handle_name ( handle ), usb_endpoint_name ( ep ), - strerror ( rc ), status ); - goto err; - } - - /* Complete transfer */ - usb_complete ( ep, iobuf ); - - return; - - err: - usb_complete_err ( ep, iobuf, rc ); -} - -/** Bulk endpoint operations */ -static struct usbio_operations usbio_bulk_out_operations = { - .open = usbio_bulk_out_open, - .close = usbio_bulk_out_close, - .poll = usbio_bulk_out_poll, -}; - -/****************************************************************************** - * - * Interrupt endpoints - * - ****************************************************************************** - * - * The EFI_USB_IO_PROTOCOL provides two ways to interact with - * interrupt endpoints, neither of which naturally model the hardware - * interaction. The UsbSyncInterruptTransfer() method allows imposes - * a 1ms overhead for every interrupt transfer (which could result in - * up to a 50% decrease in overall throughput for the device). The - * UsbAsyncInterruptTransfer() method provides no way for us to - * prevent transfers when no I/O buffers are available. - * - * We work around this design by utilising a small, fixed ring buffer - * into which the interrupt callback delivers the data. This aims to - * provide buffer space even if no I/O buffers have yet been enqueued. - * The scheme is not guaranteed since the fixed ring buffer may also - * become full. However: - * - * - devices which send a constant stream of interrupts (and which - * therefore might exhaust the fixed ring buffer) tend to be - * responding to every interrupt request, and can tolerate lost - * packets, and - * - * - devices which cannot tolerate lost interrupt packets tend to send - * only a few small messages. - * - * The scheme should therefore work in practice. - */ - -/** - * Interrupt endpoint callback - * - * @v data Received data - * @v len Length of received data - * @v context Callback context - * @v status Transfer status - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI usbio_interrupt_callback ( VOID *data, UINTN len, - VOID *context, - UINT32 status ) { - struct usbio_interrupt_ring *intr = context; - struct usbio_endpoint *endpoint = intr->endpoint; - struct usbio_device *usbio = endpoint->usbio; - struct usb_endpoint *ep = endpoint->ep; - EFI_HANDLE handle = usbio->handle; - unsigned int fill; - unsigned int index; - - /* Sanity check */ - assert ( len <= ep->mtu ); - - /* Do nothing if ring is empty */ - fill = ( intr->prod - intr->cons ); - if ( fill >= USBIO_INTR_COUNT ) { - DBGC ( usbio, "USBIO %s %s dropped interrupt completion\n", - efi_handle_name ( handle ), usb_endpoint_name ( ep ) ); - return 0; - } - - /* Do nothing if transfer was unsuccessful */ - if ( status != 0 ) { - DBGC ( usbio, "USBIO %s %s interrupt completion status %04x\n", - efi_handle_name ( handle ), usb_endpoint_name ( ep ), - status ); - return 0; /* Unclear what failure actually means here */ - } - - /* Copy data to buffer and increment producer counter */ - index = ( intr->prod % USBIO_INTR_COUNT ); - memcpy ( intr->data[index], data, len ); - intr->len[index] = len; - intr->prod++; - - return 0; -} - -/** - * Open interrupt endpoint - * - * @v endpoint Endpoint - * @ret rc Return status code - */ -static int usbio_interrupt_open ( struct usbio_endpoint *endpoint ) { - struct usbio_device *usbio = endpoint->usbio; - struct usbio_interrupt_ring *intr; - struct usb_endpoint *ep = endpoint->ep; - EFI_USB_IO_PROTOCOL *io = endpoint->io; - EFI_HANDLE handle = usbio->handle; - unsigned int interval; - unsigned int i; - void *data; - EFI_STATUS efirc; - int rc; - - /* Allocate interrupt ring buffer */ - intr = zalloc ( sizeof ( *intr ) + ( USBIO_INTR_COUNT * ep->mtu ) ); - if ( ! intr ) { - rc = -ENOMEM; - goto err_alloc; - } - endpoint->intr = intr; - intr->endpoint = endpoint; - data = ( ( ( void * ) intr ) + sizeof ( *intr ) ); - for ( i = 0 ; i < USBIO_INTR_COUNT ; i++ ) { - intr->data[i] = data; - data += ep->mtu; - } - - /* Determine polling interval */ - interval = ( ep->interval >> 3 /* microframes -> milliseconds */ ); - if ( ! interval ) - interval = 1; /* May not be zero */ - - /* Add to periodic schedule */ - if ( ( efirc = io->UsbAsyncInterruptTransfer ( io, ep->address, TRUE, - interval, ep->mtu, - usbio_interrupt_callback, - intr ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( usbio, "USBIO %s %s could not schedule interrupt " - "transfer: %s\n", efi_handle_name ( handle ), - usb_endpoint_name ( ep ), strerror ( rc ) ); - goto err_schedule; - } - - return 0; - - io->UsbAsyncInterruptTransfer ( io, ep->address, FALSE, 0, 0, - NULL, NULL ); - err_schedule: - free ( intr ); - err_alloc: - return rc; -} - -/** - * Close interrupt endpoint - * - * @v endpoint Endpoint - */ -static void usbio_interrupt_close ( struct usbio_endpoint *endpoint ) { - struct usb_endpoint *ep = endpoint->ep; - EFI_USB_IO_PROTOCOL *io = endpoint->io; - - /* Remove from periodic schedule */ - io->UsbAsyncInterruptTransfer ( io, ep->address, FALSE, 0, 0, - NULL, NULL ); - - /* Free interrupt ring buffer */ - free ( endpoint->intr ); -} - -/** - * Poll interrupt endpoint - * - * @v endpoint Endpoint - */ -static void usbio_interrupt_poll ( struct usbio_endpoint *endpoint ) { - struct usbio_interrupt_ring *intr = endpoint->intr; - struct usb_endpoint *ep = endpoint->ep; - struct io_buffer *iobuf; - unsigned int index; - unsigned int intr_index; - size_t len; - - /* Do nothing if ring is empty */ - if ( endpoint->cons == endpoint->prod ) - return; - - /* Do nothing if interrupt ring is empty */ - if ( intr->cons == intr->prod ) - return; - - /* Consume next transfer */ - index = ( endpoint->cons++ % USBIO_RING_COUNT ); - iobuf = endpoint->iobuf[index]; - - /* Populate I/O buffer */ - intr_index = ( intr->cons++ % USBIO_INTR_COUNT ); - len = intr->len[intr_index]; - assert ( len <= iob_len ( iobuf ) ); - iob_put ( iobuf, ( len - iob_len ( iobuf ) ) ); - memcpy ( iobuf->data, intr->data[intr_index], len ); - - /* Complete transfer */ - usb_complete ( ep, iobuf ); -} - -/** Interrupt endpoint operations */ -static struct usbio_operations usbio_interrupt_operations = { - .open = usbio_interrupt_open, - .close = usbio_interrupt_close, - .poll = usbio_interrupt_poll, -}; - -/****************************************************************************** - * - * Endpoint operations - * - ****************************************************************************** - */ - -/** - * Open endpoint - * - * @v ep USB endpoint - * @ret rc Return status code - */ -static int usbio_endpoint_open ( struct usb_endpoint *ep ) { - struct usb_bus *bus = ep->usb->port->hub->bus; - struct usbio_device *usbio = usb_bus_get_hostdata ( bus ); - struct usbio_endpoint *endpoint; - EFI_HANDLE handle = usbio->handle; - unsigned int attr = ( ep->attributes & USB_ENDPOINT_ATTR_TYPE_MASK ); - int interface; - int rc; - - /* Allocate and initialise structure */ - endpoint = zalloc ( sizeof ( *endpoint ) ); - if ( ! endpoint ) { - rc = -ENOMEM; - goto err_alloc; - } - usb_endpoint_set_hostdata ( ep, endpoint ); - endpoint->usbio = usbio; - endpoint->ep = ep; - - /* Identify endpoint operations */ - if ( attr == USB_ENDPOINT_ATTR_CONTROL ) { - endpoint->op = &usbio_control_operations; - } else if ( attr == USB_ENDPOINT_ATTR_BULK ) { - endpoint->op = ( ( ep->address & USB_DIR_IN ) ? - &usbio_bulk_in_operations : - &usbio_bulk_out_operations ); - } else if ( attr == USB_ENDPOINT_ATTR_INTERRUPT ) { - endpoint->op = &usbio_interrupt_operations; - } else { - rc = -ENOTSUP; - goto err_operations; - } - - /* Identify interface for this endpoint */ - interface = usbio_interface ( usbio, ep ); - if ( interface < 0 ) { - rc = interface; - goto err_interface; - } - endpoint->interface = interface; - - /* Open interface */ - if ( ( rc = usbio_open ( usbio, interface ) ) != 0 ) - goto err_open_interface; - endpoint->handle = usbio->interface[interface].handle; - endpoint->io = usbio->interface[interface].io; - DBGC ( usbio, "USBIO %s %s using ", - efi_handle_name ( handle ), usb_endpoint_name ( ep ) ); - DBGC ( usbio, "%s\n", efi_handle_name ( endpoint->handle ) ); - - /* Open endpoint */ - if ( ( rc = endpoint->op->open ( endpoint ) ) != 0 ) - goto err_open_endpoint; - - /* Add to list of endpoints */ - list_add_tail ( &endpoint->list, &usbio->endpoints ); - - return 0; - - list_del ( &endpoint->list ); - endpoint->op->close ( endpoint ); - err_open_endpoint: - usbio_close ( usbio, interface ); - err_open_interface: - err_interface: - err_operations: - free ( endpoint ); - err_alloc: - return rc; -} - -/** - * Close endpoint - * - * @v ep USB endpoint - */ -static void usbio_endpoint_close ( struct usb_endpoint *ep ) { - struct usbio_endpoint *endpoint = usb_endpoint_get_hostdata ( ep ); - struct usbio_device *usbio = endpoint->usbio; - struct io_buffer *iobuf; - unsigned int index; - - /* Remove from list of endpoints */ - list_del ( &endpoint->list ); - - /* Close endpoint */ - endpoint->op->close ( endpoint ); - - /* Close interface */ - usbio_close ( usbio, endpoint->interface ); - - /* Cancel any incomplete transfers */ - while ( endpoint->cons != endpoint->prod ) { - index = ( endpoint->cons++ % USBIO_RING_COUNT ); - iobuf = endpoint->iobuf[index]; - usb_complete_err ( ep, iobuf, -ECANCELED ); - } - - /* Free endpoint */ - free ( endpoint ); -} - -/** - * Reset endpoint - * - * @v ep USB endpoint - * @ret rc Return status code - */ -static int usbio_endpoint_reset ( struct usb_endpoint *ep __unused ) { - - /* Nothing to do */ - return 0; -} - -/** - * Update MTU - * - * @v ep USB endpoint - * @ret rc Return status code - */ -static int usbio_endpoint_mtu ( struct usb_endpoint *ep __unused ) { - - /* Nothing to do */ - return 0; -} - -/** - * Enqueue transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v flags Transfer flags - * @ret rc Return status code - */ -static int usbio_endpoint_enqueue ( struct usb_endpoint *ep, - struct io_buffer *iobuf, - unsigned int flags ) { - struct usbio_endpoint *endpoint = usb_endpoint_get_hostdata ( ep ); - unsigned int fill; - unsigned int index; - - /* Fail if transfer ring is full */ - fill = ( endpoint->prod - endpoint->cons ); - if ( fill >= USBIO_RING_COUNT ) - return -ENOBUFS; - - /* Add to ring */ - index = ( endpoint->prod++ % USBIO_RING_COUNT ); - endpoint->iobuf[index] = iobuf; - endpoint->flags[index] = flags; - - return 0; -} - -/** - * Enqueue message transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @ret rc Return status code - */ -static int usbio_endpoint_message ( struct usb_endpoint *ep, - struct io_buffer *iobuf ) { - - /* Enqueue transfer */ - return usbio_endpoint_enqueue ( ep, iobuf, USBIO_MESSAGE ); -} - -/** - * Enqueue stream transfer - * - * @v ep USB endpoint - * @v iobuf I/O buffer - * @v zlp Append a zero-length packet - * @ret rc Return status code - */ -static int usbio_endpoint_stream ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int zlp ) { - - /* Enqueue transfer */ - return usbio_endpoint_enqueue ( ep, iobuf, ( zlp ? USBIO_ZLEN : 0 ) ); -} - -/** - * Poll for completions - * - * @v endpoint Endpoint - */ -static void usbio_endpoint_poll ( struct usbio_endpoint *endpoint ) { - - /* Poll endpoint */ - endpoint->op->poll ( endpoint ); -} - -/****************************************************************************** - * - * Device operations - * - ****************************************************************************** - */ - -/** - * Open device - * - * @v usb USB device - * @ret rc Return status code - */ -static int usbio_device_open ( struct usb_device *usb ) { - struct usbio_device *usbio = - usb_bus_get_hostdata ( usb->port->hub->bus ); - - usb_set_hostdata ( usb, usbio ); - return 0; -} - -/** - * Close device - * - * @v usb USB device - */ -static void usbio_device_close ( struct usb_device *usb __unused ) { - - /* Nothing to do */ -} - -/** - * Assign device address - * - * @v usb USB device - * @ret rc Return status code - */ -static int usbio_device_address ( struct usb_device *usb __unused ) { - - /* Nothing to do */ - return 0; -} - -/****************************************************************************** - * - * Hub operations - * - ****************************************************************************** - */ - -/** - * Open hub - * - * @v hub USB hub - * @ret rc Return status code - */ -static int usbio_hub_open ( struct usb_hub *hub ) { - - /* Disallow non-root hubs */ - if ( hub->usb ) - return -ENOTSUP; - - /* Nothing to do */ - return 0; -} - -/** - * Close hub - * - * @v hub USB hub - */ -static void usbio_hub_close ( struct usb_hub *hub __unused ) { - - /* Nothing to do */ -} - -/****************************************************************************** - * - * Root hub operations - * - ****************************************************************************** - */ - -/** - * Open root hub - * - * @v hub USB hub - * @ret rc Return status code - */ -static int usbio_root_open ( struct usb_hub *hub __unused ) { - - /* Nothing to do */ - return 0; -} - -/** - * Close root hub - * - * @v hub USB hub - */ -static void usbio_root_close ( struct usb_hub *hub __unused ) { - - /* Nothing to do */ -} - -/** - * Enable port - * - * @v hub USB hub - * @v port USB port - * @ret rc Return status code - */ -static int usbio_root_enable ( struct usb_hub *hub __unused, - struct usb_port *port __unused ) { - - /* Nothing to do */ - return 0; -} - -/** - * Disable port - * - * @v hub USB hub - * @v port USB port - * @ret rc Return status code - */ -static int usbio_root_disable ( struct usb_hub *hub __unused, - struct usb_port *port __unused ) { - - /* Nothing to do */ - return 0; -} - -/** - * Update root hub port speed - * - * @v hub USB hub - * @v port USB port - * @ret rc Return status code - */ -static int usbio_root_speed ( struct usb_hub *hub __unused, - struct usb_port *port ) { - - /* Not actually exposed via EFI_USB_IO_PROTOCOL */ - port->speed = USB_SPEED_HIGH; - return 0; -} - -/** - * Clear transaction translator buffer - * - * @v hub USB hub - * @v port USB port - * @v ep USB endpoint - * @ret rc Return status code - */ -static int usbio_root_clear_tt ( struct usb_hub *hub __unused, - struct usb_port *port __unused, - struct usb_endpoint *ep __unused ) { - - /* Should never be called; this is a root hub */ - return -ENOTSUP; -} - -/****************************************************************************** - * - * Bus operations - * - ****************************************************************************** - */ - -/** - * Open USB bus - * - * @v bus USB bus - * @ret rc Return status code - */ -static int usbio_bus_open ( struct usb_bus *bus __unused ) { - - /* Nothing to do */ - return 0; -} - -/** - * Close USB bus - * - * @v bus USB bus - */ -static void usbio_bus_close ( struct usb_bus *bus __unused ) { - - /* Nothing to do */ -} - -/** - * Poll USB bus - * - * @v bus USB bus - */ -static void usbio_bus_poll ( struct usb_bus *bus ) { - struct usbio_device *usbio = usb_bus_get_hostdata ( bus ); - struct usbio_endpoint *endpoint; - - /* Poll all endpoints. We trust that completion handlers are - * minimal and will not do anything that could plausibly - * affect the endpoint list itself. - */ - list_for_each_entry ( endpoint, &usbio->endpoints, list ) - usbio_endpoint_poll ( endpoint ); -} - -/****************************************************************************** - * - * EFI driver interface - * - ****************************************************************************** - */ - -/** USB I/O host controller driver operations */ -static struct usb_host_operations usbio_operations = { - .endpoint = { - .open = usbio_endpoint_open, - .close = usbio_endpoint_close, - .reset = usbio_endpoint_reset, - .mtu = usbio_endpoint_mtu, - .message = usbio_endpoint_message, - .stream = usbio_endpoint_stream, - }, - .device = { - .open = usbio_device_open, - .close = usbio_device_close, - .address = usbio_device_address, - }, - .bus = { - .open = usbio_bus_open, - .close = usbio_bus_close, - .poll = usbio_bus_poll, - }, - .hub = { - .open = usbio_hub_open, - .close = usbio_hub_close, - }, - .root = { - .open = usbio_root_open, - .close = usbio_root_close, - .enable = usbio_root_enable, - .disable = usbio_root_disable, - .speed = usbio_root_speed, - .clear_tt = usbio_root_clear_tt, - }, -}; - -/** - * Check to see if driver supports a device - * - * @v handle EFI device handle - * @ret rc Return status code - */ -static int usbio_supported ( EFI_HANDLE handle ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_USB_DEVICE_DESCRIPTOR device; - EFI_USB_INTERFACE_DESCRIPTOR interface; - struct usb_function_descriptor desc; - struct usb_driver *driver; - struct usb_device_id *id; - union { - void *interface; - EFI_USB_IO_PROTOCOL *io; - } usb; - EFI_STATUS efirc; - int rc; - - /* Get protocol */ - if ( ( efirc = bs->OpenProtocol ( handle, &efi_usb_io_protocol_guid, - &usb.interface, efi_image_handle, - handle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ - rc = -EEFI ( efirc ); - DBGCP ( handle, "USB %s is not a USB device\n", - efi_handle_name ( handle ) ); - goto err_open_protocol; - } - - /* Get device descriptor */ - if ( ( efirc = usb.io->UsbGetDeviceDescriptor ( usb.io, - &device ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( handle, "USB %s could not get device descriptor: " - "%s\n", efi_handle_name ( handle ), strerror ( rc ) ); - goto err_get_device_descriptor; - } - memset ( &desc, 0, sizeof ( desc ) ); - desc.vendor = device.IdVendor; - desc.product = device.IdProduct; - - /* Get interface descriptor */ - if ( ( efirc = usb.io->UsbGetInterfaceDescriptor ( usb.io, - &interface ) ) !=0){ - rc = -EEFI ( efirc ); - DBGC ( handle, "USB %s could not get interface descriptor: " - "%s\n", efi_handle_name ( handle ), strerror ( rc ) ); - goto err_get_interface_descriptor; - } - desc.class.class.class = interface.InterfaceClass; - desc.class.class.subclass = interface.InterfaceSubClass; - desc.class.class.protocol = interface.InterfaceProtocol; - - /* Look for a driver for this interface */ - driver = usb_find_driver ( &desc, &id ); - if ( ! driver ) { - rc = -ENOTSUP; - goto err_unsupported; - } - - /* Success */ - rc = 0; - - err_unsupported: - err_get_interface_descriptor: - err_get_device_descriptor: - bs->CloseProtocol ( handle, &efi_usb_io_protocol_guid, - efi_image_handle, handle ); - err_open_protocol: - return rc; -} - -/** - * Fetch configuration descriptor - * - * @v usbio USB I/O device - * @ret rc Return status code - */ -static int usbio_config ( struct usbio_device *usbio ) { - EFI_HANDLE handle = usbio->handle; - EFI_USB_IO_PROTOCOL *io = usbio->io; - EFI_USB_DEVICE_DESCRIPTOR device; - EFI_USB_CONFIG_DESCRIPTOR partial; - union { - struct usb_setup_packet setup; - EFI_USB_DEVICE_REQUEST efi; - } msg; - UINT32 status; - size_t len; - unsigned int count; - unsigned int value; - unsigned int i; - EFI_STATUS efirc; - int rc; - - /* Get device descriptor */ - if ( ( efirc = io->UsbGetDeviceDescriptor ( io, &device ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( usbio, "USB %s could not get device descriptor: " - "%s\n", efi_handle_name ( handle ), strerror ( rc ) ); - goto err_get_device_descriptor; - } - count = device.NumConfigurations; - - /* Get current partial configuration descriptor */ - if ( ( efirc = io->UsbGetConfigDescriptor ( io, &partial ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( usbio, "USB %s could not get partial configuration " - "descriptor: %s\n", efi_handle_name ( handle ), - strerror ( rc ) ); - goto err_get_configuration_descriptor; - } - len = le16_to_cpu ( partial.TotalLength ); - - /* Allocate configuration descriptor */ - usbio->config = malloc ( len ); - if ( ! usbio->config ) { - rc = -ENOMEM; - goto err_alloc; - } - - /* There is, naturally, no way to retrieve the entire device - * configuration descriptor via EFI_USB_IO_PROTOCOL. Worse, - * there is no way to even retrieve the index of the current - * configuration descriptor. We have to iterate over all - * possible configuration descriptors looking for the - * descriptor that matches the current configuration value. - */ - for ( i = 0 ; i < count ; i++ ) { - - /* Construct request */ - msg.setup.request = cpu_to_le16 ( USB_GET_DESCRIPTOR ); - value = ( ( USB_CONFIGURATION_DESCRIPTOR << 8 ) | i ); - msg.setup.value = cpu_to_le16 ( value ); - msg.setup.index = 0; - msg.setup.len = cpu_to_le16 ( len ); - - /* Get full configuration descriptor */ - if ( ( efirc = io->UsbControlTransfer ( io, &msg.efi, - EfiUsbDataIn, 0, - usbio->config, len, - &status ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( usbio, "USB %s could not get configuration %d " - "descriptor: %s\n", efi_handle_name ( handle ), - i, strerror ( rc ) ); - goto err_control_transfer; - } - - /* Ignore unless this is the current configuration */ - if ( usbio->config->config != partial.ConfigurationValue ) - continue; - - /* Check length */ - if ( le16_to_cpu ( usbio->config->len ) != len ) { - DBGC ( usbio, "USB %s configuration descriptor length " - "mismatch\n", efi_handle_name ( handle ) ); - rc = -EINVAL; - goto err_len; - } - - return 0; - } - - /* No match found */ - DBGC ( usbio, "USB %s could not find current configuration " - "descriptor\n", efi_handle_name ( handle ) ); - rc = -ENOENT; - - err_len: - err_control_transfer: - free ( usbio->config ); - err_alloc: - err_get_configuration_descriptor: - err_get_device_descriptor: - return rc; -} - -/** - * Construct device path for opening other interfaces - * - * @v usbio USB I/O device - * @ret rc Return status code - */ -static int usbio_path ( struct usbio_device *usbio ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE handle = usbio->handle; - EFI_DEVICE_PATH_PROTOCOL *path; - EFI_DEVICE_PATH_PROTOCOL *end; - USB_DEVICE_PATH *usbpath; - union { - void *interface; - EFI_DEVICE_PATH_PROTOCOL *path; - } u; - size_t len; - EFI_STATUS efirc; - int rc; - - /* Open device path protocol */ - if ( ( efirc = bs->OpenProtocol ( handle, - &efi_device_path_protocol_guid, - &u.interface, efi_image_handle, - handle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){ - rc = -EEFI ( efirc ); - DBGC ( usbio, "USBIO %s cannot open device path protocol: " - "%s\n", efi_handle_name ( handle ), strerror ( rc ) ); - goto err_open_protocol; - } - path = u.interface; - - /* Locate end of device path and sanity check */ - len = efi_devpath_len ( path ); - if ( len < sizeof ( *usbpath ) ) { - DBGC ( usbio, "USBIO %s underlength device path\n", - efi_handle_name ( handle ) ); - rc = -EINVAL; - goto err_underlength; - } - usbpath = ( ( ( void * ) path ) + len - sizeof ( *usbpath ) ); - if ( ! ( ( usbpath->Header.Type == MESSAGING_DEVICE_PATH ) && - ( usbpath->Header.SubType == MSG_USB_DP ) ) ) { - DBGC ( usbio, "USBIO %s not a USB device path: ", - efi_handle_name ( handle ) ); - DBGC ( usbio, "%s\n", efi_devpath_text ( path ) ); - rc = -EINVAL; - goto err_non_usb; - } - - /* Allocate copy of device path */ - usbio->path = malloc ( len + sizeof ( *end ) ); - if ( ! usbio->path ) { - rc = -ENOMEM; - goto err_alloc; - } - memcpy ( usbio->path, path, ( len + sizeof ( *end ) ) ); - usbio->usbpath = ( ( ( void * ) usbio->path ) + len - - sizeof ( *usbpath ) ); - - /* Close protocol */ - bs->CloseProtocol ( handle, &efi_device_path_protocol_guid, - efi_image_handle, handle ); - - return 0; - - free ( usbio->path ); - err_alloc: - err_non_usb: - err_underlength: - bs->CloseProtocol ( handle, &efi_device_path_protocol_guid, - efi_image_handle, handle ); - err_open_protocol: - return rc; -} - -/** - * Construct interface list - * - * @v usbio USB I/O device - * @ret rc Return status code - */ -static int usbio_interfaces ( struct usbio_device *usbio ) { - EFI_HANDLE handle = usbio->handle; - EFI_USB_IO_PROTOCOL *io = usbio->io; - EFI_USB_INTERFACE_DESCRIPTOR interface; - unsigned int first; - unsigned int count; - EFI_STATUS efirc; - int rc; - - /* Get interface descriptor */ - if ( ( efirc = io->UsbGetInterfaceDescriptor ( io, &interface ) ) != 0){ - rc = -EEFI ( efirc ); - DBGC ( usbio, "USB %s could not get interface descriptor: " - "%s\n", efi_handle_name ( handle ), strerror ( rc ) ); - goto err_get_interface_descriptor; - } - - /* Record first interface number */ - first = interface.InterfaceNumber; - count = usbio->config->interfaces; - assert ( first < count ); - usbio->first = first; - - /* Allocate interface list */ - usbio->interface = zalloc ( count * sizeof ( usbio->interface[0] ) ); - if ( ! usbio->interface ) { - rc = -ENOMEM; - goto err_alloc; - } - - /* Use already-opened protocol for control transfers and for - * the first interface. - */ - usbio->interface[0].handle = handle; - usbio->interface[0].io = io; - usbio->interface[0].count = 1; - usbio->interface[first].handle = handle; - usbio->interface[first].io = io; - usbio->interface[first].count = 1; - - return 0; - - free ( usbio->interface ); - err_alloc: - err_get_interface_descriptor: - return rc; -} - -/** - * Attach driver to device - * - * @v efidev EFI device - * @ret rc Return status code - */ -static int usbio_start ( struct efi_device *efidev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE handle = efidev->device; - struct usbio_device *usbio; - struct usb_port *port; - union { - void *interface; - EFI_USB_IO_PROTOCOL *io; - } u; - EFI_STATUS efirc; - int rc; - - /* Allocate and initialise structure */ - usbio = zalloc ( sizeof ( *usbio ) ); - if ( ! usbio ) { - rc = -ENOMEM; - goto err_alloc; - } - efidev_set_drvdata ( efidev, usbio ); - usbio->handle = handle; - INIT_LIST_HEAD ( &usbio->endpoints ); - - /* Open USB I/O protocol */ - if ( ( efirc = bs->OpenProtocol ( handle, &efi_usb_io_protocol_guid, - &u.interface, efi_image_handle, - handle, - ( EFI_OPEN_PROTOCOL_BY_DRIVER | - EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){ - rc = -EEFI ( efirc ); - DBGC ( usbio, "USBIO %s cannot open USB I/O protocol: %s\n", - efi_handle_name ( handle ), strerror ( rc ) ); - DBGC_EFI_OPENERS ( usbio, handle, &efi_usb_io_protocol_guid ); - goto err_open_usbio; - } - usbio->io = u.io; - - /* Describe generic device */ - efi_device_info ( handle, "USB", &usbio->dev ); - usbio->dev.parent = &efidev->dev; - list_add ( &usbio->dev.siblings, &efidev->dev.children ); - INIT_LIST_HEAD ( &usbio->dev.children ); - - /* Fetch configuration descriptor */ - if ( ( rc = usbio_config ( usbio ) ) != 0 ) - goto err_config; - - /* Construct device path */ - if ( ( rc = usbio_path ( usbio ) ) != 0 ) - goto err_path; - - /* Construct interface list */ - if ( ( rc = usbio_interfaces ( usbio ) ) != 0 ) - goto err_interfaces; - - /* Allocate USB bus */ - usbio->bus = alloc_usb_bus ( &usbio->dev, 1 /* single "port" */, - USBIO_MTU, &usbio_operations ); - if ( ! usbio->bus ) { - rc = -ENOMEM; - goto err_alloc_bus; - } - usb_bus_set_hostdata ( usbio->bus, usbio ); - usb_hub_set_drvdata ( usbio->bus->hub, usbio ); - - /* Set port protocol */ - port = usb_port ( usbio->bus->hub, 1 ); - port->protocol = USB_PROTO_2_0; - - /* Register USB bus */ - if ( ( rc = register_usb_bus ( usbio->bus ) ) != 0 ) - goto err_register; - - return 0; - - unregister_usb_bus ( usbio->bus ); - err_register: - free_usb_bus ( usbio->bus ); - err_alloc_bus: - free ( usbio->interface ); - err_interfaces: - free ( usbio->path ); - err_path: - free ( usbio->config ); - err_config: - list_del ( &usbio->dev.siblings ); - bs->CloseProtocol ( handle, &efi_usb_io_protocol_guid, - efi_image_handle, handle ); - err_open_usbio: - free ( usbio ); - err_alloc: - return rc; -} - -/** - * Detach driver from device - * - * @v efidev EFI device - */ -static void usbio_stop ( struct efi_device *efidev ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE handle = efidev->device; - struct usbio_device *usbio = efidev_get_drvdata ( efidev ); - - unregister_usb_bus ( usbio->bus ); - free_usb_bus ( usbio->bus ); - free ( usbio->interface ); - free ( usbio->path ); - free ( usbio->config ); - list_del ( &usbio->dev.siblings ); - bs->CloseProtocol ( handle, &efi_usb_io_protocol_guid, - efi_image_handle, handle ); - free ( usbio ); -} - -/** EFI USB I/O driver */ -struct efi_driver usbio_driver __efi_driver ( EFI_DRIVER_NORMAL ) = { - .name = "USBIO", - .supported = usbio_supported, - .start = usbio_start, - .stop = usbio_stop, -}; diff --git a/roms/ipxe/src/drivers/usb/usbio.h b/roms/ipxe/src/drivers/usb/usbio.h deleted file mode 100644 index 1d02876f6..000000000 --- a/roms/ipxe/src/drivers/usb/usbio.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef _USBIO_H -#define _USBIO_H - -/** @file - * - * EFI_USB_IO_PROTOCOL pseudo Host Controller Interface driver - * - */ - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include <ipxe/list.h> -#include <ipxe/device.h> -#include <ipxe/efi/efi.h> -#include <ipxe/efi/Protocol/UsbIo.h> -#include <ipxe/efi/Protocol/DevicePath.h> -#include <ipxe/usb.h> - -/** USB I/O maximum transfer size - * - * The API provides no way to discover the maximum transfer size. - * Assume the 16kB supported by EHCI. - */ -#define USBIO_MTU 16384 - -/** USB I/O interrupt ring buffer size - * - * This is a policy decision. - */ -#define USBIO_INTR_COUNT 4 - -/** A USB interrupt ring buffer */ -struct usbio_interrupt_ring { - /** USB I/O endpoint */ - struct usbio_endpoint *endpoint; - /** Producer counter */ - unsigned int prod; - /** Consumer counter */ - unsigned int cons; - /** Data buffers */ - void *data[USBIO_INTR_COUNT]; - /** Lengths */ - size_t len[USBIO_INTR_COUNT]; -}; - -/** USB I/O ring buffer size - * - * This is a policy decision. - */ -#define USBIO_RING_COUNT 64 - -/** A USB I/O endpoint */ -struct usbio_endpoint { - /** USB I/O device */ - struct usbio_device *usbio; - /** USB endpoint */ - struct usb_endpoint *ep; - /** List of endpoints */ - struct list_head list; - /** USB I/O endpoint operations */ - struct usbio_operations *op; - - /** Containing interface number */ - unsigned int interface; - /** EFI handle */ - EFI_HANDLE handle; - /** USB I/O protocol */ - EFI_USB_IO_PROTOCOL *io; - - /** Producer counter */ - unsigned int prod; - /** Consumer counter */ - unsigned int cons; - /** I/O buffers */ - struct io_buffer *iobuf[USBIO_RING_COUNT]; - /** Flags */ - uint8_t flags[USBIO_RING_COUNT]; - - /** Interrupt ring buffer (if applicable) */ - struct usbio_interrupt_ring *intr; -}; - -/** USB I/O transfer flags */ -enum usbio_flags { - /** This is a message transfer */ - USBIO_MESSAGE = 0x01, - /** This transfer requires zero-length packet termination */ - USBIO_ZLEN = 0x02, -}; - -/** USB I/O endpoint operations */ -struct usbio_operations { - /** Open endpoint - * - * @v endpoint Endpoint - * @ret rc Return status code - */ - int ( * open ) ( struct usbio_endpoint *endpoint ); - /** Close endpoint - * - * @v endpoint Endpoint - */ - void ( * close ) ( struct usbio_endpoint *endpoint ); - /** Poll endpoint - * - * @v endpoint Endpoint - */ - void ( * poll ) ( struct usbio_endpoint *endpoint ); -}; - -/** A USB I/O protocol interface */ -struct usbio_interface { - /** EFI device handle */ - EFI_HANDLE handle; - /** USB I/O protocol */ - EFI_USB_IO_PROTOCOL *io; - /** Usage count */ - unsigned int count; -}; - -/** A USB I/O protocol device - * - * We model each externally-provided USB I/O protocol device as a host - * controller containing a root hub with a single port. - */ -struct usbio_device { - /** EFI device handle */ - EFI_HANDLE handle; - /** USB I/O protocol */ - EFI_USB_IO_PROTOCOL *io; - /** Generic device */ - struct device dev; - - /** Configuration descriptor */ - struct usb_configuration_descriptor *config; - - /** Device path */ - EFI_DEVICE_PATH_PROTOCOL *path; - /** Final component of USB device path */ - USB_DEVICE_PATH *usbpath; - - /** First interface number */ - uint8_t first; - /** USB I/O protocol interfaces */ - struct usbio_interface *interface; - - /** USB bus */ - struct usb_bus *bus; - /** List of endpoints */ - struct list_head endpoints; -}; - -#endif /* _USBIO_H */ diff --git a/roms/ipxe/src/drivers/usb/usbkbd.c b/roms/ipxe/src/drivers/usb/usbkbd.c index a8ab6ab76..ea94f2e63 100644 --- a/roms/ipxe/src/drivers/usb/usbkbd.c +++ b/roms/ipxe/src/drivers/usb/usbkbd.c @@ -53,14 +53,13 @@ static LIST_HEAD ( usb_keyboards ); * * @v keycode Keycode * @v modifiers Modifiers - * @v leds LED state * @ret key iPXE key * * Key codes are defined in the USB HID Usage Tables Keyboard/Keypad * page. */ -static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers, - unsigned int leds ) { +static unsigned int usbkbd_map ( unsigned int keycode, + unsigned int modifiers ) { unsigned int key; if ( keycode < USBKBD_KEY_A ) { @@ -71,8 +70,7 @@ static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers, key = ( keycode - USBKBD_KEY_A + 'a' ); if ( modifiers & USBKBD_CTRL ) { key -= ( 'a' - CTRL_A ); - } else if ( ( modifiers & USBKBD_SHIFT ) || - ( leds & USBKBD_LED_CAPS_LOCK ) ) { + } else if ( modifiers & USBKBD_SHIFT ) { key -= ( 'a' - 'A' ); } } else if ( keycode <= USBKBD_KEY_0 ) { @@ -102,22 +100,7 @@ static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP }; - key = special[ keycode - USBKBD_KEY_CAPS_LOCK ]; - } else if ( keycode <= USBKBD_KEY_PAD_ENTER ) { - /* Keypad (unaffected by Num Lock) */ - key = "\0/*-+\n" [ keycode - USBKBD_KEY_NUM_LOCK ]; - } else if ( keycode <= USBKBD_KEY_PAD_DOT ) { - /* Keypad (affected by Num Lock) */ - if ( leds & USBKBD_LED_NUM_LOCK ) { - key = "1234567890." [ keycode - USBKBD_KEY_PAD_1 ]; - } else { - static const uint16_t keypad[] = { - KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, 0, - KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PPAGE, - KEY_IC, KEY_DC - }; - key = keypad[ keycode - USBKBD_KEY_PAD_1 ]; - }; + key = special[ keycode - USBKBD_KEY_CAPSLOCK ]; } else { key = 0; } @@ -141,25 +124,10 @@ static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers, */ static void usbkbd_produce ( struct usb_keyboard *kbd, unsigned int keycode, unsigned int modifiers ) { - unsigned int leds = 0; unsigned int key; - /* Check for LED-modifying keys */ - if ( keycode == USBKBD_KEY_CAPS_LOCK ) { - leds = USBKBD_LED_CAPS_LOCK; - } else if ( keycode == USBKBD_KEY_NUM_LOCK ) { - leds = USBKBD_LED_NUM_LOCK; - } - - /* Handle LED-modifying keys */ - if ( leds ) { - kbd->leds ^= leds; - kbd->leds_changed = 1; - return; - } - /* Map to iPXE key */ - key = usbkbd_map ( keycode, modifiers, kbd->leds ); + key = usbkbd_map ( keycode, modifiers ); /* Do nothing if this keycode has no corresponding iPXE key */ if ( ! key ) { @@ -367,37 +335,6 @@ static struct usb_endpoint_driver_operations usbkbd_operations = { /****************************************************************************** * - * Keyboard LEDs - * - ****************************************************************************** - */ - -/** - * Set keyboard LEDs - * - * @v kbd USB keyboard - * @ret rc Return status code - */ -static int usbkbd_set_leds ( struct usb_keyboard *kbd ) { - struct usb_function *func = kbd->hid.func; - int rc; - - DBGC2 ( kbd, "KBD %s setting LEDs to %#02x\n", kbd->name, kbd->leds ); - - /* Set keyboard LEDs */ - if ( ( rc = usbhid_set_report ( func->usb, func->interface[0], - USBHID_REPORT_OUTPUT, 0, &kbd->leds, - sizeof ( kbd->leds ) ) ) != 0 ) { - DBGC ( kbd, "KBD %s could not set LEDs to %#02x: %s\n", - kbd->name, kbd->leds, strerror ( rc ) ); - return rc; - } - - return 0; -} - -/****************************************************************************** - * * USB interface * ****************************************************************************** @@ -425,7 +362,7 @@ static int usbkbd_probe ( struct usb_function *func, kbd->name = func->name; kbd->bus = usb->port->hub->bus; usbhid_init ( &kbd->hid, func, &usbkbd_operations, NULL ); - usb_refill_init ( &kbd->hid.in, 0, sizeof ( kbd->report ), + usb_refill_init ( &kbd->hid.in, sizeof ( kbd->report ), USBKBD_INTR_MAX_FILL ); /* Describe USB human interface device */ @@ -463,9 +400,6 @@ static int usbkbd_probe ( struct usb_function *func, /* Add to list of USB keyboards */ list_add_tail ( &kbd->list, &usb_keyboards ); - /* Set initial LED state */ - usbkbd_set_leds ( kbd ); - usb_func_set_drvdata ( func, kbd ); return 0; @@ -503,6 +437,11 @@ static struct usb_device_id usbkbd_ids[] = { .name = "kbd", .vendor = USB_ANY_ID, .product = USB_ANY_ID, + .class = { + .class = USB_CLASS_HID, + .subclass = USB_SUBCLASS_HID_BOOT, + .protocol = USBKBD_PROTOCOL, + }, }, }; @@ -510,9 +449,6 @@ static struct usb_device_id usbkbd_ids[] = { struct usb_driver usbkbd_driver __usb_driver = { .ids = usbkbd_ids, .id_count = ( sizeof ( usbkbd_ids ) / sizeof ( usbkbd_ids[0] ) ), - .class = USB_CLASS_ID ( USB_CLASS_HID, USB_SUBCLASS_HID_BOOT, - USBKBD_PROTOCOL ), - .score = USB_SCORE_NORMAL, .probe = usbkbd_probe, .remove = usbkbd_remove, }; @@ -550,20 +486,10 @@ static int usbkbd_iskey ( void ) { struct usb_keyboard *kbd; unsigned int fill; - /* Poll USB keyboards, refill endpoints, and set LEDs if applicable */ + /* Poll all USB keyboards and refill endpoints */ list_for_each_entry ( kbd, &usb_keyboards, list ) { - - /* Poll keyboard */ usb_poll ( kbd->bus ); - - /* Refill endpoints */ usb_refill ( &kbd->hid.in ); - - /* Update keyboard LEDs, if applicable */ - if ( kbd->leds_changed ) { - usbkbd_set_leds ( kbd ); - kbd->leds_changed = 0; - } } /* Check for a non-empty keyboard buffer */ diff --git a/roms/ipxe/src/drivers/usb/usbkbd.h b/roms/ipxe/src/drivers/usb/usbkbd.h index cedebfe71..7eab24e46 100644 --- a/roms/ipxe/src/drivers/usb/usbkbd.h +++ b/roms/ipxe/src/drivers/usb/usbkbd.h @@ -68,20 +68,8 @@ enum usb_keycode { USBKBD_KEY_SPACE = 0x2c, USBKBD_KEY_MINUS = 0x2d, USBKBD_KEY_SLASH = 0x38, - USBKBD_KEY_CAPS_LOCK = 0x39, - USBKBD_KEY_F1 = 0x3a, + USBKBD_KEY_CAPSLOCK = 0x39, USBKBD_KEY_UP = 0x52, - USBKBD_KEY_NUM_LOCK = 0x53, - USBKBD_KEY_PAD_ENTER = 0x58, - USBKBD_KEY_PAD_1 = 0x59, - USBKBD_KEY_PAD_DOT = 0x63, -}; - -/** USB keyboard LEDs */ -enum usb_keyboard_led { - USBKBD_LED_NUM_LOCK = 0x01, - USBKBD_LED_CAPS_LOCK = 0x02, - USBKBD_LED_SCROLL_LOCK = 0x04, }; /** Keyboard idle duration (in 4ms units) @@ -132,11 +120,6 @@ struct usb_keyboard { /** Autorepeat hold-off time (in number of completions reported) */ unsigned int holdoff; - /** Keyboard LED state */ - uint8_t leds; - /** Keyboard LEDs changed */ - uint8_t leds_changed; - /** Keyboard buffer * * This stores iPXE key values. diff --git a/roms/ipxe/src/drivers/usb/usbnet.c b/roms/ipxe/src/drivers/usb/usbnet.c index d18d81772..b92336d05 100644 --- a/roms/ipxe/src/drivers/usb/usbnet.c +++ b/roms/ipxe/src/drivers/usb/usbnet.c @@ -173,7 +173,7 @@ static int usbnet_comms_describe ( struct usbnet_device *usbnet, int rc; /* Iterate over all available interfaces */ - for ( i = 0 ; i < usbnet->func->desc.count ; i++ ) { + for ( i = 0 ; i < usbnet->func->count ; i++ ) { /* Get interface number */ comms = usbnet->func->interface[i]; @@ -217,7 +217,7 @@ static int usbnet_data_describe ( struct usbnet_device *usbnet, int rc; /* Iterate over all available interfaces */ - for ( i = 0 ; i < usbnet->func->desc.count ; i++ ) { + for ( i = 0 ; i < usbnet->func->count ; i++ ) { /* Get interface number */ data = usbnet->func->interface[i]; diff --git a/roms/ipxe/src/drivers/usb/xhci.c b/roms/ipxe/src/drivers/usb/xhci.c index 48ac6a307..49e67316b 100644 --- a/roms/ipxe/src/drivers/usb/xhci.c +++ b/roms/ipxe/src/drivers/usb/xhci.c @@ -2542,44 +2542,20 @@ static int xhci_endpoint_message ( struct usb_endpoint *ep, } /** - * Calculate number of TRBs - * - * @v len Length of data - * @v zlp Append a zero-length packet - * @ret count Number of transfer descriptors - */ -static unsigned int xhci_endpoint_count ( size_t len, int zlp ) { - unsigned int count; - - /* Split into 64kB TRBs */ - count = ( ( len + XHCI_MTU - 1 ) / XHCI_MTU ); - - /* Append a zero-length TRB if applicable */ - if ( zlp || ( count == 0 ) ) - count++; - - return count; -} - -/** * Enqueue stream transfer * * @v ep USB endpoint * @v iobuf I/O buffer - * @v zlp Append a zero-length packet + * @v terminate Terminate using a short packet * @ret rc Return status code */ static int xhci_endpoint_stream ( struct usb_endpoint *ep, - struct io_buffer *iobuf, int zlp ) { + struct io_buffer *iobuf, int terminate ) { struct xhci_endpoint *endpoint = usb_endpoint_get_hostdata ( ep ); - void *data = iobuf->data; - size_t len = iob_len ( iobuf ); - unsigned int count = xhci_endpoint_count ( len, zlp ); - union xhci_trb trbs[count]; + union xhci_trb trbs[ 1 /* Normal */ + 1 /* Possible zero-length */ ]; union xhci_trb *trb = trbs; struct xhci_trb_normal *normal; - unsigned int i; - size_t trb_len; + size_t len = iob_len ( iobuf ); int rc; /* Profile stream transfers */ @@ -2587,36 +2563,20 @@ static int xhci_endpoint_stream ( struct usb_endpoint *ep, /* Construct normal TRBs */ memset ( &trbs, 0, sizeof ( trbs ) ); - for ( i = 0 ; i < count ; i ++ ) { - - /* Calculate TRB length */ - trb_len = XHCI_MTU; - if ( trb_len > len ) - trb_len = len; - - /* Construct normal TRB */ - normal = &trb->normal; - normal->data = cpu_to_le64 ( virt_to_phys ( data ) ); - normal->len = cpu_to_le32 ( trb_len ); - normal->type = XHCI_TRB_NORMAL; + normal = &(trb++)->normal; + normal->data = cpu_to_le64 ( virt_to_phys ( iobuf->data ) ); + normal->len = cpu_to_le32 ( len ); + normal->type = XHCI_TRB_NORMAL; + if ( terminate && ( ( len & ( ep->mtu - 1 ) ) == 0 ) ) { normal->flags = XHCI_TRB_CH; - - /* Move to next TRB */ - data += trb_len; - len -= trb_len; - trb++; + normal = &(trb++)->normal; + normal->type = XHCI_TRB_NORMAL; } - - /* Mark zero-length packet (if present) as a separate transfer */ - if ( zlp && ( count > 1 ) ) - trb[-2].normal.flags = 0; - - /* Generate completion for final TRB */ - trb[-1].normal.flags = XHCI_TRB_IOC; + normal->flags = XHCI_TRB_IOC; /* Enqueue TRBs */ if ( ( rc = xhci_enqueue_multi ( &endpoint->ring, iobuf, trbs, - count ) ) != 0 ) + ( trb - trbs ) ) ) != 0 ) return rc; /* Ring the doorbell */ @@ -2759,6 +2719,7 @@ static void xhci_device_close ( struct usb_device *usb ) { static int xhci_device_address ( struct usb_device *usb ) { struct xhci_slot *slot = usb_get_hostdata ( usb ); struct xhci_device *xhci = slot->xhci; + struct usb_port *port = usb->port; struct usb_port *root_port; int psiv; int rc; @@ -2771,7 +2732,7 @@ static int xhci_device_address ( struct usb_device *usb ) { slot->port = root_port->address; /* Calculate protocol speed ID */ - psiv = xhci_port_psiv ( xhci, slot->port, usb->speed ); + psiv = xhci_port_psiv ( xhci, slot->port, port->speed ); if ( psiv < 0 ) { rc = psiv; return rc; |